aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTexas Instruments Auto Merger <lcpd_integration@list.ti.com>2015-10-13 17:30:48 -0500
committerTexas Instruments Auto Merger <lcpd_integration@list.ti.com>2015-10-13 17:30:48 -0500
commita570fd6ff74f637f907ae98211e03e8ff6327211 (patch)
tree599a75383aa942f9dd662d28eaaec5c29a7c8c26
parent8c5c15b020f1b320bb74295bd5370a14f4cb6d1e (diff)
parentf2e53c7e9090982947c47041af473d60f37fde31 (diff)
downloadjacinto6evm-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.c48
-rw-r--r--drivers/rpmsg/virtio_rpmsg_bus.c25
-rw-r--r--drivers/virtio/virtio_ring.c85
-rw-r--r--include/linux/virtio.h10
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,