.. | .. |
---|
11 | 11 | |
---|
12 | 12 | #define pr_fmt(fmt) "%s: " fmt, __func__ |
---|
13 | 13 | |
---|
14 | | -#include <linux/kernel.h> |
---|
15 | | -#include <linux/module.h> |
---|
16 | | -#include <linux/virtio.h> |
---|
17 | | -#include <linux/virtio_ids.h> |
---|
18 | | -#include <linux/virtio_config.h> |
---|
19 | | -#include <linux/scatterlist.h> |
---|
20 | 14 | #include <linux/dma-mapping.h> |
---|
21 | | -#include <linux/slab.h> |
---|
22 | 15 | #include <linux/idr.h> |
---|
23 | 16 | #include <linux/jiffies.h> |
---|
24 | | -#include <linux/sched.h> |
---|
25 | | -#include <linux/wait.h> |
---|
26 | | -#include <linux/rpmsg.h> |
---|
| 17 | +#include <linux/kernel.h> |
---|
| 18 | +#include <linux/module.h> |
---|
27 | 19 | #include <linux/mutex.h> |
---|
28 | 20 | #include <linux/of_device.h> |
---|
| 21 | +#include <linux/rpmsg.h> |
---|
| 22 | +#include <linux/scatterlist.h> |
---|
| 23 | +#include <linux/slab.h> |
---|
| 24 | +#include <linux/sched.h> |
---|
| 25 | +#include <linux/virtio.h> |
---|
| 26 | +#include <linux/virtio_byteorder.h> |
---|
| 27 | +#include <linux/virtio_ids.h> |
---|
| 28 | +#include <linux/virtio_config.h> |
---|
| 29 | +#include <linux/wait.h> |
---|
29 | 30 | |
---|
30 | 31 | #include "rpmsg_internal.h" |
---|
31 | 32 | |
---|
.. | .. |
---|
84 | 85 | * Every message sent(/received) on the rpmsg bus begins with this header. |
---|
85 | 86 | */ |
---|
86 | 87 | struct rpmsg_hdr { |
---|
87 | | - u32 src; |
---|
88 | | - u32 dst; |
---|
89 | | - u32 reserved; |
---|
90 | | - u16 len; |
---|
91 | | - u16 flags; |
---|
92 | | - u8 data[0]; |
---|
| 88 | + __virtio32 src; |
---|
| 89 | + __virtio32 dst; |
---|
| 90 | + __virtio32 reserved; |
---|
| 91 | + __virtio16 len; |
---|
| 92 | + __virtio16 flags; |
---|
| 93 | + u8 data[]; |
---|
93 | 94 | } __packed; |
---|
94 | 95 | |
---|
95 | 96 | /** |
---|
.. | .. |
---|
106 | 107 | */ |
---|
107 | 108 | struct rpmsg_ns_msg { |
---|
108 | 109 | char name[RPMSG_NAME_SIZE]; |
---|
109 | | - u32 addr; |
---|
110 | | - u32 flags; |
---|
| 110 | + __virtio32 addr; |
---|
| 111 | + __virtio32 flags; |
---|
111 | 112 | } __packed; |
---|
112 | 113 | |
---|
113 | 114 | /** |
---|
.. | .. |
---|
122 | 123 | }; |
---|
123 | 124 | |
---|
124 | 125 | /** |
---|
125 | | - * @vrp: the remote processor this channel belongs to |
---|
| 126 | + * struct virtio_rpmsg_channel - rpmsg channel descriptor |
---|
| 127 | + * @rpdev: the rpmsg channel device |
---|
| 128 | + * @vrp: the virtio remote processor device this channel belongs to |
---|
| 129 | + * |
---|
| 130 | + * This structure stores the channel that links the rpmsg device to the virtio |
---|
| 131 | + * remote processor device. |
---|
126 | 132 | */ |
---|
127 | 133 | struct virtio_rpmsg_channel { |
---|
128 | 134 | struct rpmsg_device rpdev; |
---|
.. | .. |
---|
175 | 181 | int len, u32 dst); |
---|
176 | 182 | static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, |
---|
177 | 183 | u32 dst, void *data, int len); |
---|
| 184 | +static ssize_t virtio_rpmsg_get_mtu(struct rpmsg_endpoint *ept); |
---|
178 | 185 | |
---|
179 | 186 | static const struct rpmsg_endpoint_ops virtio_endpoint_ops = { |
---|
180 | 187 | .destroy_ept = virtio_rpmsg_destroy_ept, |
---|
.. | .. |
---|
184 | 191 | .trysend = virtio_rpmsg_trysend, |
---|
185 | 192 | .trysendto = virtio_rpmsg_trysendto, |
---|
186 | 193 | .trysend_offchannel = virtio_rpmsg_trysend_offchannel, |
---|
| 194 | + .get_mtu = virtio_rpmsg_get_mtu, |
---|
187 | 195 | }; |
---|
188 | 196 | |
---|
189 | 197 | /** |
---|
.. | .. |
---|
335 | 343 | struct rpmsg_ns_msg nsm; |
---|
336 | 344 | |
---|
337 | 345 | strncpy(nsm.name, rpdev->id.name, RPMSG_NAME_SIZE); |
---|
338 | | - nsm.addr = rpdev->ept->addr; |
---|
339 | | - nsm.flags = RPMSG_NS_CREATE; |
---|
| 346 | + nsm.addr = cpu_to_virtio32(vrp->vdev, rpdev->ept->addr); |
---|
| 347 | + nsm.flags = cpu_to_virtio32(vrp->vdev, RPMSG_NS_CREATE); |
---|
340 | 348 | |
---|
341 | 349 | err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm), RPMSG_NS_ADDR); |
---|
342 | 350 | if (err) |
---|
.. | .. |
---|
359 | 367 | struct rpmsg_ns_msg nsm; |
---|
360 | 368 | |
---|
361 | 369 | strncpy(nsm.name, rpdev->id.name, RPMSG_NAME_SIZE); |
---|
362 | | - nsm.addr = rpdev->ept->addr; |
---|
363 | | - nsm.flags = RPMSG_NS_DESTROY; |
---|
| 370 | + nsm.addr = cpu_to_virtio32(vrp->vdev, rpdev->ept->addr); |
---|
| 371 | + nsm.flags = cpu_to_virtio32(vrp->vdev, RPMSG_NS_DESTROY); |
---|
364 | 372 | |
---|
365 | 373 | err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm), RPMSG_NS_ADDR); |
---|
366 | 374 | if (err) |
---|
.. | .. |
---|
612 | 620 | } |
---|
613 | 621 | } |
---|
614 | 622 | |
---|
615 | | - msg->len = len; |
---|
| 623 | + msg->len = cpu_to_virtio16(vrp->vdev, len); |
---|
616 | 624 | msg->flags = 0; |
---|
617 | | - msg->src = src; |
---|
618 | | - msg->dst = dst; |
---|
| 625 | + msg->src = cpu_to_virtio32(vrp->vdev, src); |
---|
| 626 | + msg->dst = cpu_to_virtio32(vrp->vdev, dst); |
---|
619 | 627 | msg->reserved = 0; |
---|
620 | 628 | memcpy(msg->data, data, len); |
---|
621 | 629 | |
---|
622 | 630 | dev_dbg(dev, "TX From 0x%x, To 0x%x, Len %d, Flags %d, Reserved %d\n", |
---|
623 | | - msg->src, msg->dst, msg->len, msg->flags, msg->reserved); |
---|
| 631 | + src, dst, len, msg->flags, msg->reserved); |
---|
624 | 632 | #if defined(CONFIG_DYNAMIC_DEBUG) |
---|
625 | 633 | dynamic_hex_dump("rpmsg_virtio TX: ", DUMP_PREFIX_NONE, 16, 1, |
---|
626 | | - msg, sizeof(*msg) + msg->len, true); |
---|
| 634 | + msg, sizeof(*msg) + len, true); |
---|
627 | 635 | #endif |
---|
628 | 636 | |
---|
629 | 637 | rpmsg_sg_init(&sg, msg, sizeof(*msg) + len); |
---|
.. | .. |
---|
699 | 707 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false); |
---|
700 | 708 | } |
---|
701 | 709 | |
---|
| 710 | +static ssize_t virtio_rpmsg_get_mtu(struct rpmsg_endpoint *ept) |
---|
| 711 | +{ |
---|
| 712 | + struct rpmsg_device *rpdev = ept->rpdev; |
---|
| 713 | + struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev); |
---|
| 714 | + |
---|
| 715 | + return vch->vrp->buf_size - sizeof(struct rpmsg_hdr); |
---|
| 716 | +} |
---|
| 717 | + |
---|
702 | 718 | static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev, |
---|
703 | 719 | struct rpmsg_hdr *msg, unsigned int len) |
---|
704 | 720 | { |
---|
705 | 721 | struct rpmsg_endpoint *ept; |
---|
706 | 722 | struct scatterlist sg; |
---|
| 723 | + unsigned int msg_len = virtio16_to_cpu(vrp->vdev, msg->len); |
---|
707 | 724 | int err; |
---|
708 | 725 | |
---|
709 | 726 | dev_dbg(dev, "From: 0x%x, To: 0x%x, Len: %d, Flags: %d, Reserved: %d\n", |
---|
710 | | - msg->src, msg->dst, msg->len, msg->flags, msg->reserved); |
---|
| 727 | + virtio32_to_cpu(vrp->vdev, msg->src), |
---|
| 728 | + virtio32_to_cpu(vrp->vdev, msg->dst), msg_len, |
---|
| 729 | + virtio16_to_cpu(vrp->vdev, msg->flags), |
---|
| 730 | + virtio32_to_cpu(vrp->vdev, msg->reserved)); |
---|
711 | 731 | #if defined(CONFIG_DYNAMIC_DEBUG) |
---|
712 | 732 | dynamic_hex_dump("rpmsg_virtio RX: ", DUMP_PREFIX_NONE, 16, 1, |
---|
713 | | - msg, sizeof(*msg) + msg->len, true); |
---|
| 733 | + msg, sizeof(*msg) + msg_len, true); |
---|
714 | 734 | #endif |
---|
715 | 735 | |
---|
716 | 736 | /* |
---|
.. | .. |
---|
718 | 738 | * the reported payload length. |
---|
719 | 739 | */ |
---|
720 | 740 | if (len > vrp->buf_size || |
---|
721 | | - msg->len > (len - sizeof(struct rpmsg_hdr))) { |
---|
722 | | - dev_warn(dev, "inbound msg too big: (%d, %d)\n", len, msg->len); |
---|
| 741 | + msg_len > (len - sizeof(struct rpmsg_hdr))) { |
---|
| 742 | + dev_warn(dev, "inbound msg too big: (%d, %d)\n", len, msg_len); |
---|
723 | 743 | return -EINVAL; |
---|
724 | 744 | } |
---|
725 | 745 | |
---|
726 | 746 | /* use the dst addr to fetch the callback of the appropriate user */ |
---|
727 | 747 | mutex_lock(&vrp->endpoints_lock); |
---|
728 | 748 | |
---|
729 | | - ept = idr_find(&vrp->endpoints, msg->dst); |
---|
| 749 | + ept = idr_find(&vrp->endpoints, virtio32_to_cpu(vrp->vdev, msg->dst)); |
---|
730 | 750 | |
---|
731 | 751 | /* let's make sure no one deallocates ept while we use it */ |
---|
732 | 752 | if (ept) |
---|
.. | .. |
---|
739 | 759 | mutex_lock(&ept->cb_lock); |
---|
740 | 760 | |
---|
741 | 761 | if (ept->cb) |
---|
742 | | - ept->cb(ept->rpdev, msg->data, msg->len, ept->priv, |
---|
743 | | - msg->src); |
---|
| 762 | + ept->cb(ept->rpdev, msg->data, msg_len, ept->priv, |
---|
| 763 | + virtio32_to_cpu(vrp->vdev, msg->src)); |
---|
744 | 764 | |
---|
745 | 765 | mutex_unlock(&ept->cb_lock); |
---|
746 | 766 | |
---|
.. | .. |
---|
846 | 866 | /* don't trust the remote processor for null terminating the name */ |
---|
847 | 867 | msg->name[RPMSG_NAME_SIZE - 1] = '\0'; |
---|
848 | 868 | |
---|
849 | | - dev_info(dev, "%sing channel %s addr 0x%x\n", |
---|
850 | | - msg->flags & RPMSG_NS_DESTROY ? "destroy" : "creat", |
---|
851 | | - msg->name, msg->addr); |
---|
852 | | - |
---|
853 | 869 | strncpy(chinfo.name, msg->name, sizeof(chinfo.name)); |
---|
854 | 870 | chinfo.src = RPMSG_ADDR_ANY; |
---|
855 | | - chinfo.dst = msg->addr; |
---|
| 871 | + chinfo.dst = virtio32_to_cpu(vrp->vdev, msg->addr); |
---|
856 | 872 | |
---|
857 | | - if (msg->flags & RPMSG_NS_DESTROY) { |
---|
| 873 | + dev_info(dev, "%sing channel %s addr 0x%x\n", |
---|
| 874 | + virtio32_to_cpu(vrp->vdev, msg->flags) & RPMSG_NS_DESTROY ? |
---|
| 875 | + "destroy" : "creat", msg->name, chinfo.dst); |
---|
| 876 | + |
---|
| 877 | + if (virtio32_to_cpu(vrp->vdev, msg->flags) & RPMSG_NS_DESTROY) { |
---|
858 | 878 | ret = rpmsg_unregister_device(&vrp->vdev->dev, &chinfo); |
---|
859 | 879 | if (ret) |
---|
860 | 880 | dev_err(dev, "rpmsg_destroy_channel failed: %d\n", ret); |
---|
.. | .. |
---|
920 | 940 | goto vqs_del; |
---|
921 | 941 | } |
---|
922 | 942 | |
---|
923 | | - dev_dbg(&vdev->dev, "buffers: va %p, dma %pad\n", |
---|
| 943 | + dev_dbg(&vdev->dev, "buffers: va %pK, dma %pad\n", |
---|
924 | 944 | bufs_va, &vrp->bufs_dma); |
---|
925 | 945 | |
---|
926 | 946 | /* half of the buffers is dedicated for RX */ |
---|