diff options
author | Texas Instruments Auto Merger <lcpd_integration@list.ti.com> | 2015-10-13 17:30:48 -0500 |
---|---|---|
committer | Texas Instruments Auto Merger <lcpd_integration@list.ti.com> | 2015-10-13 17:30:48 -0500 |
commit | a570fd6ff74f637f907ae98211e03e8ff6327211 (patch) | |
tree | 599a75383aa942f9dd662d28eaaec5c29a7c8c26 | |
parent | 8c5c15b020f1b320bb74295bd5370a14f4cb6d1e (diff) | |
parent | f2e53c7e9090982947c47041af473d60f37fde31 (diff) | |
download | jacinto6evm-a570fd6ff74f637f907ae98211e03e8ff6327211.tar.gz |
Merge branch 'rpmsg-ti-linux-4.1.y' of git://git.ti.com/rpmsg/rpmsg into ti-linux-4.1.y
TI-Feature: rpmsg
TI-Tree: git://git.ti.com/rpmsg/rpmsg.git
TI-Branch: rpmsg-ti-linux-4.1.y
* 'rpmsg-ti-linux-4.1.y' of git://git.ti.com/rpmsg/rpmsg:
rpmsg: fill in dma fields for sgs passed to virtio
virtio_ring: add virtqueue_add_inbuf/outbuf_rpmsg API
virtio_ring: revise descriptor addition logic for virtio_rpmsg
virtio_ring: break out vring descriptor setup code
iommu/omap: Fix debug_read_tlb() to use seq_printf()
Signed-off-by: Texas Instruments Auto Merger <lcpd_integration@list.ti.com>
-rw-r--r-- | drivers/iommu/omap-iommu-debug.c | 48 | ||||
-rw-r--r-- | drivers/rpmsg/virtio_rpmsg_bus.c | 25 | ||||
-rw-r--r-- | drivers/virtio/virtio_ring.c | 85 | ||||
-rw-r--r-- | include/linux/virtio.h | 10 |
4 files changed, 116 insertions, 52 deletions
diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c index e9f116f18531..0717aa96ce39 100644 --- a/drivers/iommu/omap-iommu-debug.c +++ b/drivers/iommu/omap-iommu-debug.c @@ -133,26 +133,18 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num) } static ssize_t iotlb_dump_cr(struct omap_iommu *obj, struct cr_regs *cr, - char *buf) + struct seq_file *s) { - char *p = buf; - - /* FIXME: Need more detail analysis of cam/ram */ - p += sprintf(p, "%08x %08x %01x\n", cr->cam, cr->ram, - (cr->cam & MMU_CAM_P) ? 1 : 0); - - return p - buf; + return seq_printf(s, "%08x %08x %01x\n", cr->cam, cr->ram, + (cr->cam & MMU_CAM_P) ? 1 : 0); } -static size_t omap_dump_tlb_entries(struct omap_iommu *obj, char *buf, - ssize_t bytes) +static size_t omap_dump_tlb_entries(struct omap_iommu *obj, struct seq_file *s) { int i, num; struct cr_regs *cr; - char *p = buf; - num = bytes / sizeof(*cr); - num = min(obj->nr_tlb_entries, num); + num = obj->nr_tlb_entries; cr = kcalloc(num, sizeof(*cr), GFP_KERNEL); if (!cr) @@ -160,40 +152,28 @@ static size_t omap_dump_tlb_entries(struct omap_iommu *obj, char *buf, num = __dump_tlb_entries(obj, cr, num); for (i = 0; i < num; i++) - p += iotlb_dump_cr(obj, cr + i, p); + iotlb_dump_cr(obj, cr + i, s); kfree(cr); - return p - buf; + return 0; } -static ssize_t debug_read_tlb(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) +static int debug_read_tlb(struct seq_file *s, void *data) { - struct omap_iommu *obj = file->private_data; - char *p, *buf; - ssize_t bytes, rest; + struct omap_iommu *obj = s->private; if (is_omap_iommu_detached(obj)) return -EPERM; - buf = kmalloc(count, GFP_KERNEL); - if (!buf) - return -ENOMEM; - p = buf; - mutex_lock(&iommu_debug_lock); - p += sprintf(p, "%8s %8s\n", "cam:", "ram:"); - p += sprintf(p, "-----------------------------------------\n"); - rest = count - (p - buf); - p += omap_dump_tlb_entries(obj, p, rest); - - bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); + seq_printf(s, "%8s %8s\n", "cam:", "ram:"); + seq_puts(s, "-----------------------------------------\n"); + omap_dump_tlb_entries(obj, s); mutex_unlock(&iommu_debug_lock); - kfree(buf); - return bytes; + return 0; } static void dump_ioptable(struct seq_file *s) @@ -268,7 +248,7 @@ static int debug_read_pagetable(struct seq_file *s, void *data) } DEBUG_FOPS_RO(regs); -DEBUG_FOPS_RO(tlb); +DEBUG_SEQ_FOPS_RO(tlb); DEBUG_SEQ_FOPS_RO(pagetable); #define __DEBUG_ADD_FILE(attr, mode) \ diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index 83f64692da76..5e416a5ca3f0 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c @@ -214,6 +214,17 @@ static void __ept_release(struct kref *kref) kfree(ept); } +static inline void rpmsg_sg_init_one(struct virtproc_info *vrp, + struct scatterlist *sg, + void *msg, unsigned int len) +{ + unsigned long offset = msg - vrp->rbufs; + + sg_init_table(sg, 1); + sg_dma_address(sg) = vrp->bufs_dma + offset; + sg_dma_len(sg) = len; +} + /* for more info, see below documentation of rpmsg_create_ept() */ static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp, struct rpmsg_channel *rpdev, rpmsg_rx_cb_t cb, @@ -825,12 +836,12 @@ int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst, msg, sizeof(*msg) + msg->len, true); #endif - sg_init_one(&sg, msg, sizeof(*msg) + len); + rpmsg_sg_init_one(vrp, &sg, msg, sizeof(*msg) + len); mutex_lock(&vrp->tx_lock); /* add message to the remote processor's virtqueue */ - err = virtqueue_add_outbuf(vrp->svq, &sg, 1, msg, GFP_KERNEL); + err = virtqueue_add_outbuf_rpmsg(vrp->svq, &sg, 1, msg, GFP_KERNEL); if (err) { /* * need to reclaim the buffer here, otherwise it's lost @@ -917,10 +928,10 @@ static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev, dev_warn(dev, "msg received with no recipient\n"); /* publish the real size of the buffer */ - sg_init_one(&sg, msg, RPMSG_BUF_SIZE); + rpmsg_sg_init_one(vrp, &sg, msg, RPMSG_BUF_SIZE); /* add the buffer back to the remote processor's virtqueue */ - err = virtqueue_add_inbuf(vrp->rvq, &sg, 1, msg, GFP_KERNEL); + err = virtqueue_add_inbuf_rpmsg(vrp->rvq, &sg, 1, msg, GFP_KERNEL); if (err < 0) { dev_err(dev, "failed to add a virtqueue buffer: %d\n", err); return err; @@ -1099,10 +1110,10 @@ static int rpmsg_probe(struct virtio_device *vdev) struct scatterlist sg; void *cpu_addr = vrp->rbufs + i * RPMSG_BUF_SIZE; - sg_init_one(&sg, cpu_addr, RPMSG_BUF_SIZE); + rpmsg_sg_init_one(vrp, &sg, cpu_addr, RPMSG_BUF_SIZE); - err = virtqueue_add_inbuf(vrp->rvq, &sg, 1, cpu_addr, - GFP_KERNEL); + err = virtqueue_add_inbuf_rpmsg(vrp->rvq, &sg, 1, cpu_addr, + GFP_KERNEL); WARN_ON(err); /* sanity check; this can't really happen */ } diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 096b857e7b75..53de0f039b95 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -120,13 +120,26 @@ static struct vring_desc *alloc_indirect(struct virtqueue *_vq, return desc; } +static inline void vring_desc_set(struct virtio_device *vdev, + struct vring_desc *desc, + struct scatterlist *sg, + u16 flags, + bool rpmsg) +{ + desc->flags = cpu_to_virtio16(vdev, flags); + desc->addr = cpu_to_virtio64(vdev, + rpmsg ? sg_dma_address(sg) : sg_phys(sg)); + desc->len = cpu_to_virtio32(vdev, rpmsg ? sg_dma_len(sg) : sg->length); +} + static inline int virtqueue_add(struct virtqueue *_vq, struct scatterlist *sgs[], unsigned int total_sg, unsigned int out_sgs, unsigned int in_sgs, void *data, - gfp_t gfp) + gfp_t gfp, + bool rpmsg) { struct vring_virtqueue *vq = to_vvq(_vq); struct scatterlist *sg; @@ -164,7 +177,7 @@ static inline int virtqueue_add(struct virtqueue *_vq, /* If the host supports indirect descriptor tables, and we have multiple * buffers, then go indirect. FIXME: tune this threshold */ - if (vq->indirect && total_sg > 1 && vq->vq.num_free) + if (!rpmsg && vq->indirect && total_sg > 1 && vq->vq.num_free) desc = alloc_indirect(_vq, total_sg, gfp); else desc = NULL; @@ -205,18 +218,17 @@ static inline int virtqueue_add(struct virtqueue *_vq, for (n = 0; n < out_sgs; n++) { for (sg = sgs[n]; sg; sg = sg_next(sg)) { - desc[i].flags = cpu_to_virtio16(_vq->vdev, VRING_DESC_F_NEXT); - desc[i].addr = cpu_to_virtio64(_vq->vdev, sg_phys(sg)); - desc[i].len = cpu_to_virtio32(_vq->vdev, sg->length); + vring_desc_set(_vq->vdev, desc + i, sg, + VRING_DESC_F_NEXT, rpmsg); prev = i; i = virtio16_to_cpu(_vq->vdev, desc[i].next); } } for (; n < (out_sgs + in_sgs); n++) { for (sg = sgs[n]; sg; sg = sg_next(sg)) { - desc[i].flags = cpu_to_virtio16(_vq->vdev, VRING_DESC_F_NEXT | VRING_DESC_F_WRITE); - desc[i].addr = cpu_to_virtio64(_vq->vdev, sg_phys(sg)); - desc[i].len = cpu_to_virtio32(_vq->vdev, sg->length); + vring_desc_set(_vq->vdev, desc + i, sg, + VRING_DESC_F_NEXT | VRING_DESC_F_WRITE, + rpmsg); prev = i; i = virtio16_to_cpu(_vq->vdev, desc[i].next); } @@ -284,7 +296,8 @@ int virtqueue_add_sgs(struct virtqueue *_vq, for (sg = sgs[i]; sg; sg = sg_next(sg)) total_sg++; } - return virtqueue_add(_vq, sgs, total_sg, out_sgs, in_sgs, data, gfp); + return virtqueue_add(_vq, sgs, total_sg, out_sgs, in_sgs, data, gfp, + false); } EXPORT_SYMBOL_GPL(virtqueue_add_sgs); @@ -306,11 +319,36 @@ int virtqueue_add_outbuf(struct virtqueue *vq, void *data, gfp_t gfp) { - return virtqueue_add(vq, &sg, num, 1, 0, data, gfp); + return virtqueue_add(vq, &sg, num, 1, 0, data, gfp, false); } EXPORT_SYMBOL_GPL(virtqueue_add_outbuf); /** + * virtqueue_add_outbuf_rpmsg - expose output buffers for virtio_rpmsg + * @vq: the struct virtqueue we're talking about. + * @sg: scatterlist (with dma fields filled in, and terminated properly!) + * @num: the number of entries in @sg readable by other side + * @data: the token identifying the buffer. + * @gfp: how to do memory allocations (if necessary). + * + * Caller must ensure we don't call this with other virtqueue operations + * at the same time (except where noted). Note that the scatterlist is + * non-standard with only the corresponding dma fields filled in, so + * should not be used with any sg operations using traditional buffer + * and length fields. + * + * Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO). + */ +int virtqueue_add_outbuf_rpmsg(struct virtqueue *vq, + struct scatterlist *sg, unsigned int num, + void *data, + gfp_t gfp) +{ + return virtqueue_add(vq, &sg, num, 1, 0, data, gfp, true); +} +EXPORT_SYMBOL_GPL(virtqueue_add_outbuf_rpmsg); + +/** * virtqueue_add_inbuf - expose input buffers to other end * @vq: the struct virtqueue we're talking about. * @sg: scatterlist (must be well-formed and terminated!) @@ -328,11 +366,36 @@ int virtqueue_add_inbuf(struct virtqueue *vq, void *data, gfp_t gfp) { - return virtqueue_add(vq, &sg, num, 0, 1, data, gfp); + return virtqueue_add(vq, &sg, num, 0, 1, data, gfp, false); } EXPORT_SYMBOL_GPL(virtqueue_add_inbuf); /** + * virtqueue_add_inbuf_rpmsg - expose input buffers for virtio_rpmsg + * @vq: the struct virtqueue we're talking about. + * @sg: scatterlist (with dma fields filled in, and terminated properly!) + * @num: the number of entries in @sg writable by other side + * @data: the token identifying the buffer. + * @gfp: how to do memory allocations (if necessary). + * + * Caller must ensure we don't call this with other virtqueue operations + * at the same time (except where noted). Note that the scatterlist is + * non-standard with only the corresponding dma fields filled in, so + * should not be used with any sg operations using traditional buffer + * and length fields. + * + * Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO). + */ +int virtqueue_add_inbuf_rpmsg(struct virtqueue *vq, + struct scatterlist *sg, unsigned int num, + void *data, + gfp_t gfp) +{ + return virtqueue_add(vq, &sg, num, 0, 1, data, gfp, true); +} +EXPORT_SYMBOL_GPL(virtqueue_add_inbuf_rpmsg); + +/** * virtqueue_kick_prepare - first half of split virtqueue_kick call. * @vq: the struct virtqueue * diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 8f4d4bfa6d46..24e6d3db70da 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -44,6 +44,16 @@ int virtqueue_add_inbuf(struct virtqueue *vq, void *data, gfp_t gfp); +int virtqueue_add_outbuf_rpmsg(struct virtqueue *vq, + struct scatterlist sg[], unsigned int num, + void *data, + gfp_t gfp); + +int virtqueue_add_inbuf_rpmsg(struct virtqueue *vq, + struct scatterlist sg[], unsigned int num, + void *data, + gfp_t gfp); + int virtqueue_add_sgs(struct virtqueue *vq, struct scatterlist *sgs[], unsigned int out_sgs, |