2012-10-30 08:52:07

by Sjur Brændeland

[permalink] [raw]
Subject: [PATCHv8 0/3]virtio_console: Add rproc_serial driver

From: Sjur Brændeland <[email protected]>

This patch-set introduces a new virtio type "rproc_serial" for communicating
with remote processors over shared memory. The driver depends on the
the remoteproc framework. As preparation for introducing "rproc_serial"
I've done a refactoring of the transmit buffer handling.

Changes since v7:
- Rebased to virtio-next branch.
- Removed extra added lines.
- Removed superfluous checks before calling reclaim_dma_bufs().
- Rusty raised some question regarding garbage collection of the
out-vq, so I moved this into a separate patch.

Thanks,
Sjur


Sjur Brændeland (3):
virtio_console: Merge struct buffer_token into struct port_buffer
virtio_console: Add support for remoteproc serial
virtio_console: Remove buffers from out_vq at port removal

drivers/char/virtio_console.c | 325 +++++++++++++++++++++++++++------------
include/uapi/linux/virtio_ids.h | 1 +
2 files changed, 230 insertions(+), 96 deletions(-)

--
1.7.9.5


2012-10-30 08:52:12

by Sjur Brændeland

[permalink] [raw]
Subject: [PATCH v8 3/3] virtio_console: Remove buffers from out_vq at port removal

From: Sjur Brændeland <[email protected]>

Remove buffers from the out-queue when a rproc_serial device
is removed. Rproc_serial communicates with remote processors
that may crash and leave buffers in the out-queue. But the
virtio_console device is not supposed to leave buffers in the
out-queue when a port is removed, so in this case throw a
warning.

Signed-off-by: Sjur Brændeland <[email protected]>
---
drivers/char/virtio_console.c | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 9ebadcb..3fa036a 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1521,6 +1521,16 @@ static void remove_port_data(struct port *port)
/* Remove buffers we queued up for the Host to send us data in. */
while ((buf = virtqueue_detach_unused_buf(port->in_vq)))
free_buf(buf, true);
+
+ /*
+ * Check the out-queue for buffers. For VIRTIO_CONSOLE it is a
+ * bug if this happens. But for RPROC_SERIAL the remote processor
+ * may have crashed, leaving buffers hanging in the out-queue.
+ */
+ while ((buf = virtqueue_detach_unused_buf(port->out_vq))) {
+ WARN_ON_ONCE(!is_rproc_serial(port->portdev->vdev));
+ free_buf(buf, true);
+ }
}

/*
--
1.7.9.5

2012-10-30 08:52:50

by Sjur Brændeland

[permalink] [raw]
Subject: [PATCH v8 1/3] virtio_console: Merge struct buffer_token into struct port_buffer

From: Sjur Brændeland <[email protected]>

Refactoring the splice functionality by unifying the approach for
sending scatter-lists and regular buffers. This simplifies
buffer handling and reduces code size. Splice will now allocate
a port_buffer and send_buf() and free_buf() can always be used
for any buffer.

Signed-off-by: Sjur Brændeland <[email protected]>
Acked-by: Amit Shah <[email protected]>
---
drivers/char/virtio_console.c | 129 +++++++++++++++++------------------------
1 file changed, 53 insertions(+), 76 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 4ad8aca..b84390f 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -111,6 +111,12 @@ struct port_buffer {
size_t len;
/* offset in the buf from which to consume data */
size_t offset;
+
+ /* If sgpages == 0 then buf is used */
+ unsigned int sgpages;
+
+ /* sg is used if spages > 0. sg must be the last in is struct */
+ struct scatterlist sg[0];
};

/*
@@ -338,17 +344,39 @@ static inline bool use_multiport(struct ports_device *portdev)

static void free_buf(struct port_buffer *buf)
{
+ unsigned int i;
+
kfree(buf->buf);
+ for (i = 0; i < buf->sgpages; i++) {
+ struct page *page = sg_page(&buf->sg[i]);
+ if (!page)
+ break;
+ put_page(page);
+ }
+
kfree(buf);
}

-static struct port_buffer *alloc_buf(size_t buf_size)
+static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size,
+ int pages)
{
struct port_buffer *buf;

- buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+ /*
+ * Allocate buffer and the sg list. The sg list array is allocated
+ * directly after the port_buffer struct.
+ */
+ buf = kmalloc(sizeof(*buf) + sizeof(struct scatterlist) * pages,
+ GFP_KERNEL);
if (!buf)
goto fail;
+
+ buf->sgpages = pages;
+ if (pages > 0) {
+ buf->buf = NULL;
+ return buf;
+ }
+
buf->buf = kmalloc(buf_size, GFP_KERNEL);
if (!buf->buf)
goto free_buf;
@@ -476,52 +504,26 @@ static ssize_t send_control_msg(struct port *port, unsigned int event,
return 0;
}

-struct buffer_token {
- union {
- void *buf;
- struct scatterlist *sg;
- } u;
- /* If sgpages == 0 then buf is used, else sg is used */
- unsigned int sgpages;
-};
-
-static void reclaim_sg_pages(struct scatterlist *sg, unsigned int nrpages)
-{
- int i;
- struct page *page;
-
- for (i = 0; i < nrpages; i++) {
- page = sg_page(&sg[i]);
- if (!page)
- break;
- put_page(page);
- }
- kfree(sg);
-}

/* Callers must take the port->outvq_lock */
static void reclaim_consumed_buffers(struct port *port)
{
- struct buffer_token *tok;
+ struct port_buffer *buf;
unsigned int len;

if (!port->portdev) {
/* Device has been unplugged. vqs are already gone. */
return;
}
- while ((tok = virtqueue_get_buf(port->out_vq, &len))) {
- if (tok->sgpages)
- reclaim_sg_pages(tok->u.sg, tok->sgpages);
- else
- kfree(tok->u.buf);
- kfree(tok);
+ while ((buf = virtqueue_get_buf(port->out_vq, &len))) {
+ free_buf(buf);
port->outvq_full = false;
}
}

static ssize_t __send_to_port(struct port *port, struct scatterlist *sg,
int nents, size_t in_count,
- struct buffer_token *tok, bool nonblock)
+ void *data, bool nonblock)
{
struct virtqueue *out_vq;
int err;
@@ -534,7 +536,7 @@ static ssize_t __send_to_port(struct port *port, struct scatterlist *sg,

reclaim_consumed_buffers(port);

- err = virtqueue_add_buf(out_vq, sg, nents, 0, tok, GFP_ATOMIC);
+ err = virtqueue_add_buf(out_vq, sg, nents, 0, data, GFP_ATOMIC);

/* Tell Host to go! */
virtqueue_kick(out_vq);
@@ -572,37 +574,6 @@ done:
return in_count;
}

-static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count,
- bool nonblock)
-{
- struct scatterlist sg[1];
- struct buffer_token *tok;
-
- tok = kmalloc(sizeof(*tok), GFP_ATOMIC);
- if (!tok)
- return -ENOMEM;
- tok->sgpages = 0;
- tok->u.buf = in_buf;
-
- sg_init_one(sg, in_buf, in_count);
-
- return __send_to_port(port, sg, 1, in_count, tok, nonblock);
-}
-
-static ssize_t send_pages(struct port *port, struct scatterlist *sg, int nents,
- size_t in_count, bool nonblock)
-{
- struct buffer_token *tok;
-
- tok = kmalloc(sizeof(*tok), GFP_ATOMIC);
- if (!tok)
- return -ENOMEM;
- tok->sgpages = nents;
- tok->u.sg = sg;
-
- return __send_to_port(port, sg, nents, in_count, tok, nonblock);
-}
-
/*
* Give out the data that's requested from the buffer that we have
* queued up.
@@ -748,9 +719,10 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
size_t count, loff_t *offp)
{
struct port *port;
- char *buf;
+ struct port_buffer *buf;
ssize_t ret;
bool nonblock;
+ struct scatterlist sg[1];

/* Userspace could be out to fool us */
if (!count)
@@ -766,11 +738,11 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,

count = min((size_t)(32 * 1024), count);

- buf = kmalloc(count, GFP_KERNEL);
+ buf = alloc_buf(port->out_vq, count, 0);
if (!buf)
return -ENOMEM;

- ret = copy_from_user(buf, ubuf, count);
+ ret = copy_from_user(buf->buf, ubuf, count);
if (ret) {
ret = -EFAULT;
goto free_buf;
@@ -784,13 +756,14 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
* through to the host.
*/
nonblock = true;
- ret = send_buf(port, buf, count, nonblock);
+ sg_init_one(sg, buf->buf, count);
+ ret = __send_to_port(port, sg, 1, count, buf, nonblock);

if (nonblock && ret > 0)
goto out;

free_buf:
- kfree(buf);
+ free_buf(buf);
out:
return ret;
}
@@ -856,6 +829,7 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe,
struct port *port = filp->private_data;
struct sg_list sgl;
ssize_t ret;
+ struct port_buffer *buf;
struct splice_desc sd = {
.total_len = len,
.flags = flags,
@@ -867,17 +841,18 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe,
if (ret < 0)
return ret;

+ buf = alloc_buf(port->out_vq, 0, pipe->nrbufs);
+ if (!buf)
+ return -ENOMEM;
+
sgl.n = 0;
sgl.len = 0;
sgl.size = pipe->nrbufs;
- sgl.sg = kmalloc(sizeof(struct scatterlist) * sgl.size, GFP_KERNEL);
- if (unlikely(!sgl.sg))
- return -ENOMEM;
-
+ sgl.sg = buf->sg;
sg_init_table(sgl.sg, sgl.size);
ret = __splice_from_pipe(pipe, &sd, pipe_to_sg);
if (likely(ret > 0))
- ret = send_pages(port, sgl.sg, sgl.n, sgl.len, true);
+ ret = __send_to_port(port, buf->sg, sgl.n, sgl.len, buf, true);

if (unlikely(ret <= 0))
kfree(sgl.sg);
@@ -1033,6 +1008,7 @@ static const struct file_operations port_fops = {
static int put_chars(u32 vtermno, const char *buf, int count)
{
struct port *port;
+ struct scatterlist sg[1];

if (unlikely(early_put_chars))
return early_put_chars(vtermno, buf, count);
@@ -1041,7 +1017,8 @@ static int put_chars(u32 vtermno, const char *buf, int count)
if (!port)
return -EPIPE;

- return send_buf(port, (void *)buf, count, false);
+ sg_init_one(sg, buf, count);
+ return __send_to_port(port, sg, 1, count, (void *)buf, false);
}

/*
@@ -1262,7 +1239,7 @@ static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock)

nr_added_bufs = 0;
do {
- buf = alloc_buf(PAGE_SIZE);
+ buf = alloc_buf(vq, PAGE_SIZE, 0);
if (!buf)
break;

--
1.7.9.5

2012-10-30 08:52:48

by Sjur Brændeland

[permalink] [raw]
Subject: [PATCH v8 2/3] virtio_console: Add support for remoteproc serial

From: Sjur Brændeland <[email protected]>

Add a simple serial connection driver called
VIRTIO_ID_RPROC_SERIAL (11) for communicating with a
remote processor in an asymmetric multi-processing
configuration.

This implementation reuses the existing virtio_console
implementation, and adds support for DMA allocation
of data buffers and disables use of tty console and
the virtio control queue.

Signed-off-by: Sjur Brændeland <[email protected]>
Acked-by: Amit Shah <[email protected]>
---
drivers/char/virtio_console.c | 190 ++++++++++++++++++++++++++++++++++-----
include/uapi/linux/virtio_ids.h | 1 +
2 files changed, 169 insertions(+), 22 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index b84390f..9ebadcb 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -37,8 +37,12 @@
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/kconfig.h>
#include "../tty/hvc/hvc_console.h"

+#define is_rproc_enabled IS_ENABLED(CONFIG_REMOTEPROC)
+
/*
* This is a global struct for storing common data for all the devices
* this driver handles.
@@ -112,6 +116,15 @@ struct port_buffer {
/* offset in the buf from which to consume data */
size_t offset;

+ /* DMA address of buffer */
+ dma_addr_t dma;
+
+ /* Device we got DMA memory from */
+ struct device *dev;
+
+ /* List of pending dma buffers to free */
+ struct list_head list;
+
/* If sgpages == 0 then buf is used */
unsigned int sgpages;

@@ -331,6 +344,11 @@ static bool is_console_port(struct port *port)
return false;
}

+static bool is_rproc_serial(const struct virtio_device *vdev)
+{
+ return is_rproc_enabled && vdev->id.device == VIRTIO_ID_RPROC_SERIAL;
+}
+
static inline bool use_multiport(struct ports_device *portdev)
{
/*
@@ -342,11 +360,13 @@ static inline bool use_multiport(struct ports_device *portdev)
return portdev->vdev->features[0] & (1 << VIRTIO_CONSOLE_F_MULTIPORT);
}

-static void free_buf(struct port_buffer *buf)
+static DEFINE_SPINLOCK(dma_bufs_lock);
+static LIST_HEAD(pending_free_dma_bufs);
+
+static void free_buf(struct port_buffer *buf, bool can_sleep)
{
unsigned int i;

- kfree(buf->buf);
for (i = 0; i < buf->sgpages; i++) {
struct page *page = sg_page(&buf->sg[i]);
if (!page)
@@ -354,14 +374,57 @@ static void free_buf(struct port_buffer *buf)
put_page(page);
}

+ if (!buf->dev) {
+ kfree(buf->buf);
+ } else if (is_rproc_enabled) {
+ unsigned long flags;
+
+ /* dma_free_coherent requires interrupts to be enabled. */
+ if (!can_sleep) {
+ /* queue up dma-buffers to be freed later */
+ spin_lock_irqsave(&dma_bufs_lock, flags);
+ list_add_tail(&buf->list, &pending_free_dma_bufs);
+ spin_unlock_irqrestore(&dma_bufs_lock, flags);
+ return;
+ }
+ dma_free_coherent(buf->dev, buf->size, buf->buf, buf->dma);
+
+ /* Release device refcnt and allow it to be freed */
+ put_device(buf->dev);
+ }
+
kfree(buf);
}

+static void reclaim_dma_bufs(void)
+{
+ unsigned long flags;
+ struct port_buffer *buf, *tmp;
+ LIST_HEAD(tmp_list);
+
+ if (list_empty(&pending_free_dma_bufs))
+ return;
+
+ /* Create a copy of the pending_free_dma_bufs while holding the lock */
+ spin_lock_irqsave(&dma_bufs_lock, flags);
+ list_cut_position(&tmp_list, &pending_free_dma_bufs,
+ pending_free_dma_bufs.prev);
+ spin_unlock_irqrestore(&dma_bufs_lock, flags);
+
+ /* Release the dma buffers, without irqs enabled */
+ list_for_each_entry_safe(buf, tmp, &tmp_list, list) {
+ list_del(&buf->list);
+ free_buf(buf, true);
+ }
+}
+
static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size,
int pages)
{
struct port_buffer *buf;

+ reclaim_dma_bufs();
+
/*
* Allocate buffer and the sg list. The sg list array is allocated
* directly after the port_buffer struct.
@@ -373,11 +436,34 @@ static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size,

buf->sgpages = pages;
if (pages > 0) {
+ buf->dev = NULL;
buf->buf = NULL;
return buf;
}

- buf->buf = kmalloc(buf_size, GFP_KERNEL);
+ if (is_rproc_serial(vq->vdev)) {
+ /*
+ * Allocate DMA memory from ancestor. When a virtio
+ * device is created by remoteproc, the DMA memory is
+ * associated with the grandparent device:
+ * vdev => rproc => platform-dev.
+ * The code here would have been less quirky if
+ * DMA_MEMORY_INCLUDES_CHILDREN had been supported
+ * in dma-coherent.c
+ */
+ if (!vq->vdev->dev.parent || !vq->vdev->dev.parent->parent)
+ goto free_buf;
+ buf->dev = vq->vdev->dev.parent->parent;
+
+ /* Increase device refcnt to avoid freeing it */
+ get_device(buf->dev);
+ buf->buf = dma_alloc_coherent(buf->dev, buf_size, &buf->dma,
+ GFP_KERNEL);
+ } else {
+ buf->dev = NULL;
+ buf->buf = kmalloc(buf_size, GFP_KERNEL);
+ }
+
if (!buf->buf)
goto free_buf;
buf->len = 0;
@@ -444,7 +530,7 @@ static void discard_port_data(struct port *port)
port->stats.bytes_discarded += buf->len - buf->offset;
if (add_inbuf(port->in_vq, buf) < 0) {
err++;
- free_buf(buf);
+ free_buf(buf, false);
}
port->inbuf = NULL;
buf = get_inbuf(port);
@@ -516,7 +602,7 @@ static void reclaim_consumed_buffers(struct port *port)
return;
}
while ((buf = virtqueue_get_buf(port->out_vq, &len))) {
- free_buf(buf);
+ free_buf(buf, false);
port->outvq_full = false;
}
}
@@ -763,7 +849,7 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
goto out;

free_buf:
- free_buf(buf);
+ free_buf(buf, true);
out:
return ret;
}
@@ -837,6 +923,15 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe,
.u.data = &sgl,
};

+ /*
+ * Rproc_serial does not yet support splice. To support splice
+ * pipe_to_sg() must allocate dma-buffers and copy content from
+ * regular pages to dma pages. And alloc_buf and free_buf must
+ * support allocating and freeing such a list of dma-buffers.
+ */
+ if (is_rproc_serial(port->out_vq->vdev))
+ return -EINVAL;
+
ret = wait_port_writable(port, filp->f_flags & O_NONBLOCK);
if (ret < 0)
return ret;
@@ -855,7 +950,7 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe,
ret = __send_to_port(port, buf->sg, sgl.n, sgl.len, buf, true);

if (unlikely(ret <= 0))
- kfree(sgl.sg);
+ free_buf(buf, true);
return ret;
}

@@ -904,6 +999,7 @@ static int port_fops_release(struct inode *inode, struct file *filp)
reclaim_consumed_buffers(port);
spin_unlock_irq(&port->outvq_lock);

+ reclaim_dma_bufs();
/*
* Locks aren't necessary here as a port can't be opened after
* unplug, and if a port isn't unplugged, a kref would already
@@ -1055,7 +1151,10 @@ static void resize_console(struct port *port)
return;

vdev = port->portdev->vdev;
- if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE))
+
+ /* Don't test F_SIZE at all if we're rproc: not a valid feature! */
+ if (!is_rproc_serial(vdev) &&
+ virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE))
hvc_resize(port->cons.hvc, port->cons.ws);
}

@@ -1247,7 +1346,7 @@ static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock)
ret = add_inbuf(vq, buf);
if (ret < 0) {
spin_unlock_irq(lock);
- free_buf(buf);
+ free_buf(buf, true);
break;
}
nr_added_bufs++;
@@ -1335,10 +1434,18 @@ static int add_port(struct ports_device *portdev, u32 id)
goto free_device;
}

- /*
- * If we're not using multiport support, this has to be a console port
- */
- if (!use_multiport(port->portdev)) {
+ if (is_rproc_serial(port->portdev->vdev))
+ /*
+ * For rproc_serial assume remote processor is connected.
+ * rproc_serial does not want the console port, only
+ * the generic port implementation.
+ */
+ port->host_connected = true;
+ else if (!use_multiport(port->portdev)) {
+ /*
+ * If we're not using multiport support,
+ * this has to be a console port.
+ */
err = init_port_console(port);
if (err)
goto free_inbufs;
@@ -1371,7 +1478,7 @@ static int add_port(struct ports_device *portdev, u32 id)

free_inbufs:
while ((buf = virtqueue_detach_unused_buf(port->in_vq)))
- free_buf(buf);
+ free_buf(buf, true);
free_device:
device_destroy(pdrvdata.class, port->dev->devt);
free_cdev:
@@ -1413,7 +1520,7 @@ static void remove_port_data(struct port *port)

/* Remove buffers we queued up for the Host to send us data in. */
while ((buf = virtqueue_detach_unused_buf(port->in_vq)))
- free_buf(buf);
+ free_buf(buf, true);
}

/*
@@ -1615,7 +1722,7 @@ static void control_work_handler(struct work_struct *work)
if (add_inbuf(portdev->c_ivq, buf) < 0) {
dev_warn(&portdev->vdev->dev,
"Error adding buffer to queue\n");
- free_buf(buf);
+ free_buf(buf, false);
}
}
spin_unlock(&portdev->cvq_lock);
@@ -1811,10 +1918,10 @@ static void remove_controlq_data(struct ports_device *portdev)
return;

while ((buf = virtqueue_get_buf(portdev->c_ivq, &len)))
- free_buf(buf);
+ free_buf(buf, true);

while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq)))
- free_buf(buf);
+ free_buf(buf, true);
}

/*
@@ -1861,11 +1968,15 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)

multiport = false;
portdev->config.max_nr_ports = 1;
- if (virtio_config_val(vdev, VIRTIO_CONSOLE_F_MULTIPORT,
- offsetof(struct virtio_console_config,
- max_nr_ports),
- &portdev->config.max_nr_ports) == 0)
+
+ /* Don't test MULTIPORT at all if we're rproc: not a valid feature! */
+ if (!is_rproc_serial(vdev) &&
+ virtio_config_val(vdev, VIRTIO_CONSOLE_F_MULTIPORT,
+ offsetof(struct virtio_console_config,
+ max_nr_ports),
+ &portdev->config.max_nr_ports) == 0) {
multiport = true;
+ }

err = init_vqs(portdev);
if (err < 0) {
@@ -1975,6 +2086,16 @@ static unsigned int features[] = {
VIRTIO_CONSOLE_F_MULTIPORT,
};

+static struct virtio_device_id rproc_serial_id_table[] = {
+#if IS_ENABLED(CONFIG_REMOTEPROC)
+ { VIRTIO_ID_RPROC_SERIAL, VIRTIO_DEV_ANY_ID },
+#endif
+ { 0 },
+};
+
+static unsigned int rproc_serial_features[] = {
+};
+
#ifdef CONFIG_PM
static int virtcons_freeze(struct virtio_device *vdev)
{
@@ -2059,6 +2180,20 @@ static struct virtio_driver virtio_console = {
#endif
};

+/*
+ * virtio_rproc_serial refers to __devinit function which causes
+ * section mismatch warnings. So use __refdata to silence warnings.
+ */
+static struct virtio_driver __refdata virtio_rproc_serial = {
+ .feature_table = rproc_serial_features,
+ .feature_table_size = ARRAY_SIZE(rproc_serial_features),
+ .driver.name = "virtio_rproc_serial",
+ .driver.owner = THIS_MODULE,
+ .id_table = rproc_serial_id_table,
+ .probe = virtcons_probe,
+ .remove = virtcons_remove,
+};
+
static int __init init(void)
{
int err;
@@ -2083,7 +2218,15 @@ static int __init init(void)
pr_err("Error %d registering virtio driver\n", err);
goto free;
}
+ err = register_virtio_driver(&virtio_rproc_serial);
+ if (err < 0) {
+ pr_err("Error %d registering virtio rproc serial driver\n",
+ err);
+ goto unregister;
+ }
return 0;
+unregister:
+ unregister_virtio_driver(&virtio_console);
free:
if (pdrvdata.debugfs_dir)
debugfs_remove_recursive(pdrvdata.debugfs_dir);
@@ -2093,7 +2236,10 @@ free:

static void __exit fini(void)
{
+ reclaim_dma_bufs();
+
unregister_virtio_driver(&virtio_console);
+ unregister_virtio_driver(&virtio_rproc_serial);

class_destroy(pdrvdata.class);
if (pdrvdata.debugfs_dir)
diff --git a/include/uapi/linux/virtio_ids.h b/include/uapi/linux/virtio_ids.h
index 270fb22..a7630d0 100644
--- a/include/uapi/linux/virtio_ids.h
+++ b/include/uapi/linux/virtio_ids.h
@@ -37,5 +37,6 @@
#define VIRTIO_ID_RPMSG 7 /* virtio remote processor messaging */
#define VIRTIO_ID_SCSI 8 /* virtio scsi */
#define VIRTIO_ID_9P 9 /* 9p virtio console */
+#define VIRTIO_ID_RPROC_SERIAL 11 /* virtio remoteproc serial link */

#endif /* _LINUX_VIRTIO_IDS_H */
--
1.7.9.5

2012-11-04 23:47:49

by Rusty Russell

[permalink] [raw]
Subject: Re: [PATCHv8 0/3]virtio_console: Add rproc_serial driver

Sjur Brændeland <[email protected]> writes:

> From: Sjur Brændeland <[email protected]>
>
> This patch-set introduces a new virtio type "rproc_serial" for communicating
> with remote processors over shared memory. The driver depends on the
> the remoteproc framework. As preparation for introducing "rproc_serial"
> I've done a refactoring of the transmit buffer handling.
>
> Changes since v7:
> - Rebased to virtio-next branch.
> - Removed extra added lines.
> - Removed superfluous checks before calling reclaim_dma_bufs().
> - Rusty raised some question regarding garbage collection of the
> out-vq, so I moved this into a separate patch.

OK, I'm not sure that WARN_ON won't fire, but that's not all that
harmful.

Applied,
Rusty.

2012-11-05 10:32:06

by Amit Shah

[permalink] [raw]
Subject: Re: [PATCHv8 0/3]virtio_console: Add rproc_serial driver

On (Mon) 05 Nov 2012 [09:11:45], Rusty Russell wrote:
> Sjur Br?ndeland <[email protected]> writes:
>
> > From: Sjur Br?ndeland <[email protected]>
> >
> > This patch-set introduces a new virtio type "rproc_serial" for communicating
> > with remote processors over shared memory. The driver depends on the
> > the remoteproc framework. As preparation for introducing "rproc_serial"
> > I've done a refactoring of the transmit buffer handling.
> >
> > Changes since v7:
> > - Rebased to virtio-next branch.
> > - Removed extra added lines.
> > - Removed superfluous checks before calling reclaim_dma_bufs().
> > - Rusty raised some question regarding garbage collection of the
> > out-vq, so I moved this into a separate patch.
>
> OK, I'm not sure that WARN_ON won't fire, but that's not all that
> harmful.

Sjur said he'll send out a respin for this; can you wait for his v8?

Amit

2012-11-05 10:32:04

by Amit Shah

[permalink] [raw]
Subject: Re: [PATCHv8 0/3]virtio_console: Add rproc_serial driver

On (Mon) 05 Nov 2012 [11:31:24], Amit Shah wrote:
> On (Mon) 05 Nov 2012 [09:11:45], Rusty Russell wrote:
> > Sjur Br?ndeland <[email protected]> writes:
> >
> > > From: Sjur Br?ndeland <[email protected]>
> > >
> > > This patch-set introduces a new virtio type "rproc_serial" for communicating
> > > with remote processors over shared memory. The driver depends on the
> > > the remoteproc framework. As preparation for introducing "rproc_serial"
> > > I've done a refactoring of the transmit buffer handling.
> > >
> > > Changes since v7:
> > > - Rebased to virtio-next branch.
> > > - Removed extra added lines.
> > > - Removed superfluous checks before calling reclaim_dma_bufs().
> > > - Rusty raised some question regarding garbage collection of the
> > > out-vq, so I moved this into a separate patch.
> >
> > OK, I'm not sure that WARN_ON won't fire, but that's not all that
> > harmful.
>
> Sjur said he'll send out a respin for this; can you wait for his v8?

Er, v9.

Amit

2012-11-06 02:10:42

by Rusty Russell

[permalink] [raw]
Subject: Re: [PATCHv8 0/3]virtio_console: Add rproc_serial driver

Amit Shah <[email protected]> writes:
> On (Mon) 05 Nov 2012 [11:31:24], Amit Shah wrote:
>> On (Mon) 05 Nov 2012 [09:11:45], Rusty Russell wrote:
>> > Sjur Brændeland <[email protected]> writes:
>> >
>> > > From: Sjur Brændeland <[email protected]>
>> > >
>> > > This patch-set introduces a new virtio type "rproc_serial" for communicating
>> > > with remote processors over shared memory. The driver depends on the
>> > > the remoteproc framework. As preparation for introducing "rproc_serial"
>> > > I've done a refactoring of the transmit buffer handling.
>> > >
>> > > Changes since v7:
>> > > - Rebased to virtio-next branch.
>> > > - Removed extra added lines.
>> > > - Removed superfluous checks before calling reclaim_dma_bufs().
>> > > - Rusty raised some question regarding garbage collection of the
>> > > out-vq, so I moved this into a separate patch.
>> >
>> > OK, I'm not sure that WARN_ON won't fire, but that's not all that
>> > harmful.
>>
>> Sjur said he'll send out a respin for this; can you wait for his v8?
>
> Er, v9.
>
> Amit

Yep, they're in my pending-rebases tree now.

Though no need to repost the whole series; just the changes please.

Cheers,
Rusty.

2012-11-08 09:06:48

by Amit Shah

[permalink] [raw]
Subject: Re: [PATCHv8 0/3]virtio_console: Add rproc_serial driver

On (Tue) 30 Oct 2012 [09:51:50], Sjur Br?ndeland wrote:
> From: Sjur Br?ndeland <[email protected]>
>
> This patch-set introduces a new virtio type "rproc_serial" for communicating
> with remote processors over shared memory. The driver depends on the
> the remoteproc framework. As preparation for introducing "rproc_serial"
> I've done a refactoring of the transmit buffer handling.

Thanks, Sjur.

Please pick the virtio spec from

https://github.com/rustyrussell/virtio-spec

and update the spec with info for remote-proc.

Thanks,
Amit