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

rpmsg: virtio: Register the rpmsg_char device

Instantiate the rpmsg_char device on virtio RPMsg bus creation.
This provides the capability, with the RPMSG_CREATE_EPT_IOCTL ioctl,
to create RPMsg char device endpoints relying on the
rpmsg_chrdev_create_eptdev API.

Notice that the created endpoints are attached to the rpmsg_ctldev
device, but not associated to a channel.
As consequence, the endpoint source and destination addresses have to
been specified and there is no channel creation and no name service
announcement to inform the remote side.

Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
Link: https://lore.kernel.org/r/20210311140413.31725-6-arnaud.pouliquen@foss.st.com
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>

authored by

Arnaud Pouliquen and committed by
Bjorn Andersson
c486682a b4ce7e2e

+57 -5
+57 -5
drivers/rpmsg/virtio_rpmsg_bus.c
··· 813 813 wake_up_interruptible(&vrp->sendq); 814 814 } 815 815 816 + /* 817 + * Called to expose to user a /dev/rpmsg_ctrlX interface allowing to 818 + * create endpoint-to-endpoint communication without associated RPMsg channel. 819 + * The endpoints are rattached to the ctrldev RPMsg device. 820 + */ 821 + static struct rpmsg_device *rpmsg_virtio_add_ctrl_dev(struct virtio_device *vdev) 822 + { 823 + struct virtproc_info *vrp = vdev->priv; 824 + struct virtio_rpmsg_channel *vch; 825 + struct rpmsg_device *rpdev_ctrl; 826 + int err = 0; 827 + 828 + vch = kzalloc(sizeof(*vch), GFP_KERNEL); 829 + if (!vch) 830 + return ERR_PTR(-ENOMEM); 831 + 832 + /* Link the channel to the vrp */ 833 + vch->vrp = vrp; 834 + 835 + /* Assign public information to the rpmsg_device */ 836 + rpdev_ctrl = &vch->rpdev; 837 + rpdev_ctrl->ops = &virtio_rpmsg_ops; 838 + 839 + rpdev_ctrl->dev.parent = &vrp->vdev->dev; 840 + rpdev_ctrl->dev.release = virtio_rpmsg_release_device; 841 + rpdev_ctrl->little_endian = virtio_is_little_endian(vrp->vdev); 842 + 843 + err = rpmsg_chrdev_register_device(rpdev_ctrl); 844 + if (err) { 845 + kfree(vch); 846 + return ERR_PTR(err); 847 + } 848 + 849 + return rpdev_ctrl; 850 + } 851 + 852 + static void rpmsg_virtio_del_ctrl_dev(struct rpmsg_device *rpdev_ctrl) 853 + { 854 + if (!rpdev_ctrl) 855 + return; 856 + kfree(to_virtio_rpmsg_channel(rpdev_ctrl)); 857 + } 858 + 816 859 static int rpmsg_probe(struct virtio_device *vdev) 817 860 { 818 861 vq_callback_t *vq_cbs[] = { rpmsg_recv_done, rpmsg_xmit_done }; 819 862 static const char * const names[] = { "input", "output" }; 820 863 struct virtqueue *vqs[2]; 821 864 struct virtproc_info *vrp; 822 - struct virtio_rpmsg_channel *vch; 823 - struct rpmsg_device *rpdev_ns; 865 + struct virtio_rpmsg_channel *vch = NULL; 866 + struct rpmsg_device *rpdev_ns, *rpdev_ctrl; 824 867 void *bufs_va; 825 868 int err = 0, i; 826 869 size_t total_buf_space; ··· 937 894 938 895 vdev->priv = vrp; 939 896 897 + rpdev_ctrl = rpmsg_virtio_add_ctrl_dev(vdev); 898 + if (IS_ERR(rpdev_ctrl)) { 899 + err = PTR_ERR(rpdev_ctrl); 900 + goto free_coherent; 901 + } 902 + 940 903 /* if supported by the remote processor, enable the name service */ 941 904 if (virtio_has_feature(vdev, VIRTIO_RPMSG_F_NS)) { 942 905 vch = kzalloc(sizeof(*vch), GFP_KERNEL); 943 906 if (!vch) { 944 907 err = -ENOMEM; 945 - goto free_coherent; 908 + goto free_ctrldev; 946 909 } 947 910 948 911 /* Link the channel to our vrp */ ··· 964 915 965 916 err = rpmsg_ns_register_device(rpdev_ns); 966 917 if (err) 967 - goto free_coherent; 918 + goto free_vch; 968 919 } 969 920 970 921 /* ··· 988 939 989 940 return 0; 990 941 991 - free_coherent: 942 + free_vch: 992 943 kfree(vch); 944 + free_ctrldev: 945 + rpmsg_virtio_del_ctrl_dev(rpdev_ctrl); 946 + free_coherent: 993 947 dma_free_coherent(vdev->dev.parent, total_buf_space, 994 948 bufs_va, vrp->bufs_dma); 995 949 vqs_del: