Commit dbc88dce7e5fef5c13e3f27eef5f857b8cb082ce
1 parent
eef5dab813
Exists in
ti-lsk-linux-4.1.y
and in
5 other branches
rpmsg: fill in dma fields for sgs passed to virtio
The virtio_rpmsg bus allocates the vring buffers using the dma_alloc_coherent() API, and passes them to the virtio core using the virtqueue_add_inbuf/outbuf() API. This API takes in a scatterlist which is prepared using the returned virtual address from the above dma allocation API. The virtio core expects the descriptors to be allocated from linear address space in general, but the dma_alloc_coherent() API can return virtual addresses from the vmalloc range if the underlying memory is allocated from a carveout or a CMA pool in highmem. This patch fills in the dma fields of the scatterlist structure, and uses the newly added virtqueue_add_inbuf/outbuf_rpmsg() API to pass these to the virtio core, so that the virtio core can use sg_dma_address() API instead of sg_phys() API and thereby fill in properly the physical addresses of the vring buffers in the vring transport. Based on a RFC patch from Edgar E. Iglesias <edgar.iglesias@xilinx.com>, http://marc.info/?l=linux-virtualization&m=143047903512230&w=2 Suggested-by: Russell King <linux@arm.linux.org.uk> Signed-off-by: Suman Anna <s-anna@ti.com>
Showing 1 changed file with 18 additions and 7 deletions Side-by-side Diff
drivers/rpmsg/virtio_rpmsg_bus.c
... | ... | @@ -214,6 +214,17 @@ |
214 | 214 | kfree(ept); |
215 | 215 | } |
216 | 216 | |
217 | +static inline void rpmsg_sg_init_one(struct virtproc_info *vrp, | |
218 | + struct scatterlist *sg, | |
219 | + void *msg, unsigned int len) | |
220 | +{ | |
221 | + unsigned long offset = msg - vrp->rbufs; | |
222 | + | |
223 | + sg_init_table(sg, 1); | |
224 | + sg_dma_address(sg) = vrp->bufs_dma + offset; | |
225 | + sg_dma_len(sg) = len; | |
226 | +} | |
227 | + | |
217 | 228 | /* for more info, see below documentation of rpmsg_create_ept() */ |
218 | 229 | static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp, |
219 | 230 | struct rpmsg_channel *rpdev, rpmsg_rx_cb_t cb, |
220 | 231 | |
... | ... | @@ -825,12 +836,12 @@ |
825 | 836 | msg, sizeof(*msg) + msg->len, true); |
826 | 837 | #endif |
827 | 838 | |
828 | - sg_init_one(&sg, msg, sizeof(*msg) + len); | |
839 | + rpmsg_sg_init_one(vrp, &sg, msg, sizeof(*msg) + len); | |
829 | 840 | |
830 | 841 | mutex_lock(&vrp->tx_lock); |
831 | 842 | |
832 | 843 | /* add message to the remote processor's virtqueue */ |
833 | - err = virtqueue_add_outbuf(vrp->svq, &sg, 1, msg, GFP_KERNEL); | |
844 | + err = virtqueue_add_outbuf_rpmsg(vrp->svq, &sg, 1, msg, GFP_KERNEL); | |
834 | 845 | if (err) { |
835 | 846 | /* |
836 | 847 | * need to reclaim the buffer here, otherwise it's lost |
837 | 848 | |
... | ... | @@ -917,10 +928,10 @@ |
917 | 928 | dev_warn(dev, "msg received with no recipient\n"); |
918 | 929 | |
919 | 930 | /* publish the real size of the buffer */ |
920 | - sg_init_one(&sg, msg, RPMSG_BUF_SIZE); | |
931 | + rpmsg_sg_init_one(vrp, &sg, msg, RPMSG_BUF_SIZE); | |
921 | 932 | |
922 | 933 | /* add the buffer back to the remote processor's virtqueue */ |
923 | - err = virtqueue_add_inbuf(vrp->rvq, &sg, 1, msg, GFP_KERNEL); | |
934 | + err = virtqueue_add_inbuf_rpmsg(vrp->rvq, &sg, 1, msg, GFP_KERNEL); | |
924 | 935 | if (err < 0) { |
925 | 936 | dev_err(dev, "failed to add a virtqueue buffer: %d\n", err); |
926 | 937 | return err; |
927 | 938 | |
... | ... | @@ -1099,10 +1110,10 @@ |
1099 | 1110 | struct scatterlist sg; |
1100 | 1111 | void *cpu_addr = vrp->rbufs + i * RPMSG_BUF_SIZE; |
1101 | 1112 | |
1102 | - sg_init_one(&sg, cpu_addr, RPMSG_BUF_SIZE); | |
1113 | + rpmsg_sg_init_one(vrp, &sg, cpu_addr, RPMSG_BUF_SIZE); | |
1103 | 1114 | |
1104 | - err = virtqueue_add_inbuf(vrp->rvq, &sg, 1, cpu_addr, | |
1105 | - GFP_KERNEL); | |
1115 | + err = virtqueue_add_inbuf_rpmsg(vrp->rvq, &sg, 1, cpu_addr, | |
1116 | + GFP_KERNEL); | |
1106 | 1117 | WARN_ON(err); /* sanity check; this can't really happen */ |
1107 | 1118 | } |
1108 | 1119 |