Commit dbc88dce7e5fef5c13e3f27eef5f857b8cb082ce

Authored by Suman Anna
1 parent eef5dab813

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