| .. | .. |
|---|
| 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; |
|---|
| .. | .. |
|---|
| 335 | 341 | struct rpmsg_ns_msg nsm; |
|---|
| 336 | 342 | |
|---|
| 337 | 343 | strncpy(nsm.name, rpdev->id.name, RPMSG_NAME_SIZE); |
|---|
| 338 | | - nsm.addr = rpdev->ept->addr; |
|---|
| 339 | | - nsm.flags = RPMSG_NS_CREATE; |
|---|
| 344 | + nsm.addr = cpu_to_virtio32(vrp->vdev, rpdev->ept->addr); |
|---|
| 345 | + nsm.flags = cpu_to_virtio32(vrp->vdev, RPMSG_NS_CREATE); |
|---|
| 340 | 346 | |
|---|
| 341 | 347 | err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm), RPMSG_NS_ADDR); |
|---|
| 342 | 348 | if (err) |
|---|
| .. | .. |
|---|
| 359 | 365 | struct rpmsg_ns_msg nsm; |
|---|
| 360 | 366 | |
|---|
| 361 | 367 | strncpy(nsm.name, rpdev->id.name, RPMSG_NAME_SIZE); |
|---|
| 362 | | - nsm.addr = rpdev->ept->addr; |
|---|
| 363 | | - nsm.flags = RPMSG_NS_DESTROY; |
|---|
| 368 | + nsm.addr = cpu_to_virtio32(vrp->vdev, rpdev->ept->addr); |
|---|
| 369 | + nsm.flags = cpu_to_virtio32(vrp->vdev, RPMSG_NS_DESTROY); |
|---|
| 364 | 370 | |
|---|
| 365 | 371 | err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm), RPMSG_NS_ADDR); |
|---|
| 366 | 372 | if (err) |
|---|
| .. | .. |
|---|
| 612 | 618 | } |
|---|
| 613 | 619 | } |
|---|
| 614 | 620 | |
|---|
| 615 | | - msg->len = len; |
|---|
| 621 | + msg->len = cpu_to_virtio16(vrp->vdev, len); |
|---|
| 616 | 622 | msg->flags = 0; |
|---|
| 617 | | - msg->src = src; |
|---|
| 618 | | - msg->dst = dst; |
|---|
| 623 | + msg->src = cpu_to_virtio32(vrp->vdev, src); |
|---|
| 624 | + msg->dst = cpu_to_virtio32(vrp->vdev, dst); |
|---|
| 619 | 625 | msg->reserved = 0; |
|---|
| 620 | 626 | memcpy(msg->data, data, len); |
|---|
| 621 | 627 | |
|---|
| 622 | 628 | 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); |
|---|
| 629 | + src, dst, len, msg->flags, msg->reserved); |
|---|
| 624 | 630 | #if defined(CONFIG_DYNAMIC_DEBUG) |
|---|
| 625 | 631 | dynamic_hex_dump("rpmsg_virtio TX: ", DUMP_PREFIX_NONE, 16, 1, |
|---|
| 626 | | - msg, sizeof(*msg) + msg->len, true); |
|---|
| 632 | + msg, sizeof(*msg) + len, true); |
|---|
| 627 | 633 | #endif |
|---|
| 628 | 634 | |
|---|
| 629 | 635 | rpmsg_sg_init(&sg, msg, sizeof(*msg) + len); |
|---|
| .. | .. |
|---|
| 704 | 710 | { |
|---|
| 705 | 711 | struct rpmsg_endpoint *ept; |
|---|
| 706 | 712 | struct scatterlist sg; |
|---|
| 713 | + unsigned int msg_len = virtio16_to_cpu(vrp->vdev, msg->len); |
|---|
| 707 | 714 | int err; |
|---|
| 708 | 715 | |
|---|
| 709 | 716 | 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); |
|---|
| 717 | + virtio32_to_cpu(vrp->vdev, msg->src), |
|---|
| 718 | + virtio32_to_cpu(vrp->vdev, msg->dst), msg_len, |
|---|
| 719 | + virtio16_to_cpu(vrp->vdev, msg->flags), |
|---|
| 720 | + virtio32_to_cpu(vrp->vdev, msg->reserved)); |
|---|
| 711 | 721 | #if defined(CONFIG_DYNAMIC_DEBUG) |
|---|
| 712 | 722 | dynamic_hex_dump("rpmsg_virtio RX: ", DUMP_PREFIX_NONE, 16, 1, |
|---|
| 713 | | - msg, sizeof(*msg) + msg->len, true); |
|---|
| 723 | + msg, sizeof(*msg) + msg_len, true); |
|---|
| 714 | 724 | #endif |
|---|
| 715 | 725 | |
|---|
| 716 | 726 | /* |
|---|
| .. | .. |
|---|
| 718 | 728 | * the reported payload length. |
|---|
| 719 | 729 | */ |
|---|
| 720 | 730 | 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); |
|---|
| 731 | + msg_len > (len - sizeof(struct rpmsg_hdr))) { |
|---|
| 732 | + dev_warn(dev, "inbound msg too big: (%d, %d)\n", len, msg_len); |
|---|
| 723 | 733 | return -EINVAL; |
|---|
| 724 | 734 | } |
|---|
| 725 | 735 | |
|---|
| 726 | 736 | /* use the dst addr to fetch the callback of the appropriate user */ |
|---|
| 727 | 737 | mutex_lock(&vrp->endpoints_lock); |
|---|
| 728 | 738 | |
|---|
| 729 | | - ept = idr_find(&vrp->endpoints, msg->dst); |
|---|
| 739 | + ept = idr_find(&vrp->endpoints, virtio32_to_cpu(vrp->vdev, msg->dst)); |
|---|
| 730 | 740 | |
|---|
| 731 | 741 | /* let's make sure no one deallocates ept while we use it */ |
|---|
| 732 | 742 | if (ept) |
|---|
| .. | .. |
|---|
| 739 | 749 | mutex_lock(&ept->cb_lock); |
|---|
| 740 | 750 | |
|---|
| 741 | 751 | if (ept->cb) |
|---|
| 742 | | - ept->cb(ept->rpdev, msg->data, msg->len, ept->priv, |
|---|
| 743 | | - msg->src); |
|---|
| 752 | + ept->cb(ept->rpdev, msg->data, msg_len, ept->priv, |
|---|
| 753 | + virtio32_to_cpu(vrp->vdev, msg->src)); |
|---|
| 744 | 754 | |
|---|
| 745 | 755 | mutex_unlock(&ept->cb_lock); |
|---|
| 746 | 756 | |
|---|
| .. | .. |
|---|
| 846 | 856 | /* don't trust the remote processor for null terminating the name */ |
|---|
| 847 | 857 | msg->name[RPMSG_NAME_SIZE - 1] = '\0'; |
|---|
| 848 | 858 | |
|---|
| 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 | 859 | strncpy(chinfo.name, msg->name, sizeof(chinfo.name)); |
|---|
| 854 | 860 | chinfo.src = RPMSG_ADDR_ANY; |
|---|
| 855 | | - chinfo.dst = msg->addr; |
|---|
| 861 | + chinfo.dst = virtio32_to_cpu(vrp->vdev, msg->addr); |
|---|
| 856 | 862 | |
|---|
| 857 | | - if (msg->flags & RPMSG_NS_DESTROY) { |
|---|
| 863 | + dev_info(dev, "%sing channel %s addr 0x%x\n", |
|---|
| 864 | + virtio32_to_cpu(vrp->vdev, msg->flags) & RPMSG_NS_DESTROY ? |
|---|
| 865 | + "destroy" : "creat", msg->name, chinfo.dst); |
|---|
| 866 | + |
|---|
| 867 | + if (virtio32_to_cpu(vrp->vdev, msg->flags) & RPMSG_NS_DESTROY) { |
|---|
| 858 | 868 | ret = rpmsg_unregister_device(&vrp->vdev->dev, &chinfo); |
|---|
| 859 | 869 | if (ret) |
|---|
| 860 | 870 | dev_err(dev, "rpmsg_destroy_channel failed: %d\n", ret); |
|---|
| .. | .. |
|---|
| 920 | 930 | goto vqs_del; |
|---|
| 921 | 931 | } |
|---|
| 922 | 932 | |
|---|
| 923 | | - dev_dbg(&vdev->dev, "buffers: va %p, dma %pad\n", |
|---|
| 933 | + dev_dbg(&vdev->dev, "buffers: va %pK, dma %pad\n", |
|---|
| 924 | 934 | bufs_va, &vrp->bufs_dma); |
|---|
| 925 | 935 | |
|---|
| 926 | 936 | /* half of the buffers is dedicated for RX */ |
|---|