[PATCHv2] Revert "virtio_console: Initialize guest_connected=true for rproc_serial"

2013-03-13 Thread sjur . brandeland
From: Sjur Brændeland 


This reverts commit 8078db789a92b10ff6e2d713231b5367e014c53b, and
adds a lengthy comment explaining the problem area.

The reverted patch caused opening of ports to fail for rproc_serial.
In probe guest_connected was set to true, but port_fops_open()
fails with -EMFILE if guest_connected already is true.

Signed-off-by: Sjur Brændeland 
---
 drivers/char/virtio_console.c |   22 --
 1 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index e905d5f..e6ba6b7 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1436,7 +1436,7 @@ static int add_port(struct ports_device *portdev, u32 id)
 * rproc_serial does not want the console port, only
 * the generic port implementation.
 */
-   port->host_connected = port->guest_connected = true;
+   port->host_connected = true;
else if (!use_multiport(port->portdev)) {
/*
 * If we're not using multiport support,
@@ -1752,13 +1752,23 @@ static void in_intr(struct virtqueue *vq)
port->inbuf = get_inbuf(port);
 
/*
-* Don't queue up data when port is closed.  This condition
+* Normally the port should not accept data when the port is
+* closed. For generic serial ports, the host won't (shouldn't)
+* send data till the guest is connected. But this condition
 * can be reached when a console port is not yet connected (no
-* tty is spawned) and the host sends out data to console
-* ports.  For generic serial ports, the host won't
-* (shouldn't) send data till the guest is connected.
+* tty is spawned) and the other side sends out data over the
+* vring, or when a remote devices start sending data before
+* the ports are opened.
+*
+* A generic serial port will discard data if not connected,
+* while console ports and rproc-serial ports accepts data at
+* any time. rproc-serial is initiated with guest_connected to
+* false because port_fops_open expects this. Console ports are
+* hooked up with an HVC console and is initialized with
+* guest_connected to true.
 */
-   if (!port->guest_connected)
+
+   if (!port->guest_connected && !is_rproc_serial(port->portdev->vdev))
discard_port_data(port);
 
spin_unlock_irqrestore(&port->inbuf_lock, flags);
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCH] Revert "virtio_console: Initialize guest_connected=true for rproc_serial"

2013-03-11 Thread sjur . brandeland
From: Sjur Brændeland 

This reverts commit 8078db789a92b10ff6e2d713231b5367e014c53b.

The reverted patch caused opening of ports to fail for rproc_serial.
In probe guest_connected was set to true, but port_fops_open()
fails with -EMFILE if guest_connected already is true.

Signed-off-by: Sjur Brændeland 
---
Hi Rusty,

Here is a fix intended for 3.9.
Sorry for the churn here :-(

Regards,
Sjur

 drivers/char/virtio_console.c |7 +--
 1 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index e905d5f..031be0b 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1436,7 +1436,7 @@ static int add_port(struct ports_device *portdev, u32 id)
 * rproc_serial does not want the console port, only
 * the generic port implementation.
 */
-   port->host_connected = port->guest_connected = true;
+   port->host_connected = true;
else if (!use_multiport(port->portdev)) {
/*
 * If we're not using multiport support,
@@ -1757,8 +1757,11 @@ static void in_intr(struct virtqueue *vq)
 * tty is spawned) and the host sends out data to console
 * ports.  For generic serial ports, the host won't
 * (shouldn't) send data till the guest is connected.
+* However a remote device might send data before the port is
+* connected. So don't remove data from a rproc_serial device.
 */
-   if (!port->guest_connected)
+
+   if (!port->guest_connected && !is_rproc_serial(port->portdev->vdev))
discard_port_data(port);
 
spin_unlock_irqrestore(&port->inbuf_lock, flags);
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCHv2] virtio: Introduce vringh wrappers in virtio_config

2013-03-08 Thread sjur . brandeland
From: Sjur Brændeland 

Add wrappers for the host vrings to support loose
coupling between the virtio device and driver.

A new struct vringh_config_ops with the functions
find_vrhs() and del_vrhs() is added to the virtio_device
struct. This enables virtio drivers to manage virtio
host rings without detailed knowledge of how the
vrings are created and deleted.

The function vringh_notify() is added so vringh clients
can notify the other side that buffers are added to the
used-ring.

Cc: Ohad Ben-Cohen 
Cc: Rusty Russell 
Signed-off-by: Sjur Brændeland 
---
Hi Rusty,

>It's weird that you conflate the host and guest ring sides in rpmsg, but
>that might make sense if they're really bound together.

Weird or not, CAIF-virtio is design to use guest rings for TX traffic,
and host rings for RX traffic. The motivation for this design is to allow
zero-copy in the data-path on the remote-device/modem.

Changes since v1:
- Moved find_vrhs() and del_vrhs() to a separate struct vringh_config_ops.
- Moved definition of struct vringh_config_ops into vringh.h
- Added vringh_config field to struct virtio_device
- Removed priv pointer field from struct vringh

There are a number of different ways to do this, let me know if you
want this changed in any way.

Thanks,
Sjur


 include/linux/virtio.h |3 +++
 include/linux/vringh.h |   29 +
 2 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index 00ccc40..5b71fc1 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /**
  * virtqueue - a queue to register buffers for sending or receiving.
@@ -70,6 +71,7 @@ static inline unsigned int virtqueue_get_queue_index(struct 
virtqueue *vq)
  * @dev: underlying device.
  * @id: the device type identification (used to match it with a driver).
  * @config: the configuration ops for this device.
+ * @vringh_config: configuration ops for host vrings.
  * @vqs: the list of virtqueues for this device.
  * @features: the features supported by both driver and device.
  * @priv: private pointer for the driver's use.
@@ -79,6 +81,7 @@ struct virtio_device {
struct device dev;
struct virtio_device_id id;
struct virtio_config_ops *config;
+   struct vringh_config_ops *vringh_config;
struct list_head vqs;
/* Note that this is a Linux set_bit-style bitmap. */
unsigned long features[1];
diff --git a/include/linux/vringh.h b/include/linux/vringh.h
index ab41185..c7d9289 100644
--- a/include/linux/vringh.h
+++ b/include/linux/vringh.h
@@ -50,6 +50,28 @@ struct vringh {
 
/* The vring (note: it may contain user pointers!) */
struct vring vring;
+
+   /* The function to call to notify the guest about added buffers */
+   void (*notify)(struct vringh *);
+};
+
+/**
+ * struct vringh_config_ops - ops for creating a host vring from a virtio 
driver
+ * @find_vrhs: find the host vrings and instantiate them
+ * vdev: the virtio_device
+ * nhvrs: the number of host vrings to find
+ * hvrs: on success, includes new host vrings
+ * callbacks: array of driver callbacks, for each host vring
+ * include a NULL entry for vqs that do not need a callback
+ * Returns 0 on success or error status
+ * @del_vrhs: free the host vrings found by find_vrhs().
+ */
+struct virtio_device;
+typedef void vrh_callback_t(struct virtio_device *, struct vringh *);
+struct vringh_config_ops {
+   int (*find_vrhs)(struct virtio_device *vdev, unsigned nhvrs,
+struct vringh *vrhs[], vrh_callback_t *callbacks[]);
+   void (*del_vrhs)(struct virtio_device *vdev);
 };
 
 /* The memory the vring can access, and what offset to apply. */
@@ -182,4 +204,11 @@ void vringh_notify_disable_kern(struct vringh *vrh);
 
 int vringh_need_notify_kern(struct vringh *vrh);
 
+/* Notify the guest about buffers added to the used ring */
+static inline void vringh_notify(struct vringh *vrh)
+{
+   if (vrh->notify)
+   vrh->notify(vrh);
+}
+
 #endif /* _LINUX_VRINGH_H */
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCH vringh] virtio: Introduce vringh wrappers in virtio_config

2013-03-05 Thread sjur . brandeland
From: Sjur Brændeland 

Add wrappers for the host vrings to support loose
coupling between the virtio device and driver.

The functions find_vrhs() and del_vrhs() are added to
struct virtio_config_ops to manage the host vrings.
The function vringh_notify() is added so the guest
can be kicked when buffers are added to the used-ring.

This enables the virtio drivers to manage the virtio rings
without knowledge of how the host vrings are managed.

Cc: Ohad Ben-Cohen 
Signed-off-by: Sjur Brændeland 
---
 include/linux/virtio_config.h |   13 +
 include/linux/vringh.h|   13 +
 2 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index 29b9104..88dd5ae 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -51,7 +51,17 @@
  *  This returns a pointer to the bus name a la pci_name from which
  *  the caller can then copy.
  * @set_vq_affinity: set the affinity for a virtqueue.
+ * @find_vrhs: find the host vrings and instantiate them
+ * vdev: the virtio_device
+ * nhvrs: the number of host vrings to find
+ * hvrs: on success, includes new host vrings
+ * callbacks: array of driver callbacks, for each host vring
+ * include a NULL entry for vqs that do not need a callback
+ * Returns 0 on success or error status
+ * @del_vrhs: free the host vrings found by find_vrhs().
  */
+struct vringh;
+typedef void vrh_callback_t(struct virtio_device *, struct vringh *);
 typedef void vq_callback_t(struct virtqueue *);
 struct virtio_config_ops {
void (*get)(struct virtio_device *vdev, unsigned offset,
@@ -70,6 +80,9 @@ struct virtio_config_ops {
void (*finalize_features)(struct virtio_device *vdev);
const char *(*bus_name)(struct virtio_device *vdev);
int (*set_vq_affinity)(struct virtqueue *vq, int cpu);
+   int (*find_vrhs)(struct virtio_device *vdev, unsigned nhvrs,
+struct vringh *vrhs[], vrh_callback_t *callbacks[]);
+   void (*del_vrhs)(struct virtio_device *vdev);
 };
 
 /* If driver didn't advertise the feature, it will never appear. */
diff --git a/include/linux/vringh.h b/include/linux/vringh.h
index ab41185..8156f51 100644
--- a/include/linux/vringh.h
+++ b/include/linux/vringh.h
@@ -50,6 +50,12 @@ struct vringh {
 
/* The vring (note: it may contain user pointers!) */
struct vring vring;
+
+   /* The function to call when buffers are available */
+   void (*notify)(struct vringh *);
+
+   /* A pointer for the vringh clients to use. */
+   void *priv;
 };
 
 /* The memory the vring can access, and what offset to apply. */
@@ -182,4 +188,11 @@ void vringh_notify_disable_kern(struct vringh *vrh);
 
 int vringh_need_notify_kern(struct vringh *vrh);
 
+/* Notify the guest about buffers added to the used ring */
+static inline void vringh_notify(struct vringh *vrh)
+{
+   if (vrh->notify)
+   vrh->notify(vrh);
+}
+
 #endif /* _LINUX_VRINGH_H */
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCH] virtio_console: Initialize guest_connected=true for rproc_serial

2013-02-12 Thread sjur . brandeland
From: Sjur Brændeland 

When rproc_serial is initialized, guest_connected should be set
to true. We can then revert the extra checks introduced in
commit: "virtio_console: Let unconnected rproc device receive data."

Signed-off-by: Sjur Brændeland 
---
 drivers/char/virtio_console.c |7 ++-
 1 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 2cfd5a0..5afc8f6 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1436,7 +1436,7 @@ static int add_port(struct ports_device *portdev, u32 id)
 * rproc_serial does not want the console port, only
 * the generic port implementation.
 */
-   port->host_connected = true;
+   port->host_connected = port->guest_connected = true;
else if (!use_multiport(port->portdev)) {
/*
 * If we're not using multiport support,
@@ -1757,11 +1757,8 @@ static void in_intr(struct virtqueue *vq)
 * tty is spawned) and the host sends out data to console
 * ports.  For generic serial ports, the host won't
 * (shouldn't) send data till the guest is connected.
-* However a remote device might send data before the port is
-* connected. So don't remove data from a rproc_serial device.
 */
-
-   if (!port->guest_connected && !is_rproc_serial(port->portdev->vdev))
+   if (!port->guest_connected)
discard_port_data(port);
 
spin_unlock_irqrestore(&port->inbuf_lock, flags);
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCHv2 vringh 3/3] caif_virtio: Introduce caif over virtio

2013-02-12 Thread sjur . brandeland
From: Vikram ARV 

Add the the Virtio shared memory driver for STE Modems.
caif_virtio is implemented utilizing the virtio framework
for data transport and is managed with the remoteproc frameworks.

The Virtio queue is used for transmitting data to the modem, and
the new vringh implementation is receiving data over the vring.

Signed-off-by: Vikram ARV 
Signed-off-by: Sjur Brændeland 

cc: David S. Miller 
cc: Ohad Ben-Cohen 
cc: Rusty Russell 
cc: Ido Yariv 
cc: Erwan Yvin 
---
As mentioned earlier this patch-set will go via Rusty's git.

Changes since V1: 
- update to new vringh API, 
- use module_virtio_driver macro
- call tasklet_kill from cfv_remove().

Thanks,
Sjur

 drivers/net/caif/Kconfig|8 +
 drivers/net/caif/Makefile   |3 +
 drivers/net/caif/caif_virtio.c  |  547 +++
 include/linux/virtio_caif.h |   24 ++
 include/uapi/linux/virtio_ids.h |1 +
 5 files changed, 583 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/caif/caif_virtio.c
 create mode 100644 include/linux/virtio_caif.h

diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig
index abf4d7a..a8b67e9 100644
--- a/drivers/net/caif/Kconfig
+++ b/drivers/net/caif/Kconfig
@@ -47,3 +47,11 @@ config CAIF_HSI
The caif low level driver for CAIF over HSI.
Be aware that if you enable this then you also need to
enable a low-level HSI driver.
+
+config CAIF_VIRTIO
+   tristate "CAIF virtio transport driver"
+   depends on CAIF
+   depends on REMOTEPROC
+   default n
+   ---help---
+   The caif driver for CAIF over Virtio.
diff --git a/drivers/net/caif/Makefile b/drivers/net/caif/Makefile
index 91dff86..d9ee26a 100644
--- a/drivers/net/caif/Makefile
+++ b/drivers/net/caif/Makefile
@@ -13,3 +13,6 @@ obj-$(CONFIG_CAIF_SHM) += caif_shm.o
 
 # HSI interface
 obj-$(CONFIG_CAIF_HSI) += caif_hsi.o
+
+# Virtio interface
+obj-$(CONFIG_CAIF_VIRTIO) += caif_virtio.o
diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c
new file mode 100644
index 000..d4f339c
--- /dev/null
+++ b/drivers/net/caif/caif_virtio.c
@@ -0,0 +1,547 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2012
+ * Contact: Sjur Brendeland / sjur.brandel...@stericsson.com
+ * Authors: Vicram Arv / vikram@stericsson.com,
+ * Dmitry Tarnyagin / dmitry.tarnya...@stericsson.com
+ * Sjur Brendeland / sjur.brandel...@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Vicram Arv ");
+MODULE_AUTHOR("Sjur Brendeland vdev->priv;
+   tasklet_schedule(&cfv->tx_release_tasklet);
+}
+
+/* This is invoked whenever the remote processor completed processing
+ * a TX msg we just sent it, and the buffer is put back to the used ring.
+ */
+static void cfv_release_used_buf(struct virtqueue *vq_tx)
+{
+   struct cfv_info *cfv = vq_tx->vdev->priv;
+   unsigned long flags;
+
+   BUG_ON(vq_tx != cfv->vq_tx);
+   WARN_ON_ONCE(irqs_disabled());
+
+   for (;;) {
+   unsigned int len;
+   struct token_info *buf_info;
+
+   /* Get used buffer from used ring to recycle used descriptors */
+   spin_lock_irqsave(&cfv->tx_lock, flags);
+   buf_info = virtqueue_get_buf(vq_tx, &len);
+
+   if (!buf_info)
+   goto out;
+
+   BUG_ON(!cfv->queued_tx);
+   if (--cfv->queued_tx <= cfv->watermark_tx) {
+   cfv->watermark_tx = 0;
+   netif_tx_wake_all_queues(cfv->ndev);
+   }
+   spin_unlock_irqrestore(&cfv->tx_lock, flags);
+
+   dma_free_coherent(vq_tx->vdev->dev.parent->parent,
+ buf_info->size, buf_info->vaddr,
+ buf_info->dma_handle);
+   kfree(buf_info);
+   }
+   return;
+out:
+   spin_unlock_irqrestore(&cfv->tx_lock, flags);
+}
+
+static struct sk_buff *cfv_alloc_and_copy_skb(int *err,
+ struct cfv_info *cfv,
+ u8 *frm, u32 frm_len)
+{
+   struct sk_buff *skb;
+   u32 cfpkt_len, pad_len;
+
+   *err = 0;
+   /* Verify that packet size with down-link header and mtu size */
+   if (frm_len > cfv->mru || frm_len <= cfv->rx_hr + cfv->rx_tr) {
+   netdev_err(cfv->ndev,
+  "Invalid frmlen:%u  mtu:%u hr:%d tr:%d\n",
+  frm_len, cfv->mru,  cfv->rx_hr,
+  cfv->rx_tr);
+   *err = -EPROTO;
+   return NULL;
+   }
+
+   cfpkt_len = frm_len - (cfv->rx_hr + cfv->rx_tr);
+
+   pad_len = (unsigned long)(frm + cfv->rx_hr) & (IP_HDR_ALIGN - 1);

[PATCHv2 vringh 2/3] virtio: Add module driver macro for virtio drivers.

2013-02-12 Thread sjur . brandeland
From: Sjur Brændeland 

Add helper macro for drivers that don't do anything
special in module init/exit.

Signed-off-by: Sjur Brændeland 
---
 include/linux/virtio.h |9 +
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index cf8adb1..00ccc40 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -126,4 +126,13 @@ static inline struct virtio_driver *drv_to_virtio(struct 
device_driver *drv)
 
 int register_virtio_driver(struct virtio_driver *drv);
 void unregister_virtio_driver(struct virtio_driver *drv);
+
+/* module_virtio_driver() - Helper macro for drivers that don't do
+ * anything special in module init/exit.  This eliminates a lot of
+ * boilerplate.  Each module may only use this macro once, and
+ * calling it replaces module_init() and module_exit()
+ */
+#define module_virtio_driver(__virtio_driver) \
+   module_driver(__virtio_driver, register_virtio_driver, \
+   unregister_virtio_driver)
 #endif /* _LINUX_VIRTIO_H */
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCHv2 vringh 1/3] remoteproc: Add support for vringh (Host vrings)

2013-02-12 Thread sjur . brandeland
From: Sjur Brændeland 

Add functions for creating, deleting and kicking host-side virtio rings.

The host ring is not integrated with virtiqueues and cannot be managed
through virtio-config. Remoteproc must export functions for handling the
host-side virtio rings.

The functions rproc_virtio_get_vringh(), rproc_virtio_del_vringh(),
rproc_virtio_kick_vringh() are added to remoteproc_virtio.c. The
existing functions rproc_vq_interrupt() and rproc_virtio_find_vqs()
are updated to handle the new vhost rings.

Signed-off-by: Sjur Brændeland 
cc: Ohad Ben-Cohen 
cc: Rusty Russell 
cc: Ido Yariv 
cc: Erwan Yvin 
---
 drivers/remoteproc/Kconfig |3 +
 drivers/remoteproc/remoteproc_virtio.c |  127 ++--
 include/linux/remoteproc.h |   14 
 3 files changed, 137 insertions(+), 7 deletions(-)

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 96ce101..c7d1d36 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -7,6 +7,9 @@ config REMOTEPROC
depends on HAS_DMA
select FW_CONFIG
select VIRTIO
+   select VHOST_RING
+
+source drivers/vhost/Kconfig
 
 config OMAP_REMOTEPROC
tristate "OMAP remoteproc support"
diff --git a/drivers/remoteproc/remoteproc_virtio.c 
b/drivers/remoteproc/remoteproc_virtio.c
index 9e198e5..fa7bf7b 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -60,10 +61,15 @@ irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int 
notifyid)
dev_dbg(&rproc->dev, "vq index %d is interrupted\n", notifyid);
 
rvring = idr_find(&rproc->notifyids, notifyid);
-   if (!rvring || !rvring->vq)
+   if (!rvring)
return IRQ_NONE;
 
-   return vring_interrupt(0, rvring->vq);
+   if (rvring->vringh && rvring->vringh_cb)
+   return rvring->vringh_cb(&rvring->rvdev->vdev, rvring->vringh);
+   else if (rvring->vq)
+   return vring_interrupt(0, rvring->vq);
+   else
+   return IRQ_NONE;
 }
 EXPORT_SYMBOL(rproc_vq_interrupt);
 
@@ -149,14 +155,21 @@ static int rproc_virtio_find_vqs(struct virtio_device 
*vdev, unsigned nvqs,
   const char *names[])
 {
struct rproc *rproc = vdev_to_rproc(vdev);
-   int i, ret;
+   struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
+   int rng, id, ret, nrings = ARRAY_SIZE(rvdev->vring);
+
+   for (id = 0, rng = 0; rng < nrings; ++rng) {
+   struct rproc_vring *rvring = &rvdev->vring[rng];
+   /* Skip the host side rings */
+   if (rvring->vringh)
+   continue;
 
-   for (i = 0; i < nvqs; ++i) {
-   vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i]);
-   if (IS_ERR(vqs[i])) {
-   ret = PTR_ERR(vqs[i]);
+   vqs[id] = rp_find_vq(vdev, rng, callbacks[id], names[id]);
+   if (IS_ERR(vqs[id])) {
+   ret = PTR_ERR(vqs[id]);
goto error;
}
+   ++id;
}
 
/* now that the vqs are all set, boot the remote processor */
@@ -173,6 +186,106 @@ error:
return ret;
 }
 
+/**
+ * rproc_virtio_new_vringh() - create a reversed virtio ring.
+ * @vdev: the virtio device
+ * @index: the virtio ring index
+ * @cb: callback for the reversed virtio ring
+ *
+ * This function should be called by the virtio-driver
+ * before calling find_vqs(). It returns a struct vringh for
+ * accessing the virtio ring.
+ *
+ * Return: struct vhost, or NULL upon error.
+ */
+struct vringh *
+rproc_virtio_new_vringh(struct virtio_device *vdev, unsigned index,
+   irqreturn_t (*cb)(struct virtio_device *vdev,
+ struct vringh *vring))
+{
+   struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
+   struct rproc_vring *rvring;
+   struct vringh *vrh;
+   int err;
+
+   if (index > ARRAY_SIZE(rvdev->vring)) {
+   dev_err(&rvdev->vdev.dev, "bad vring index: %d\n", index);
+   return NULL;
+   }
+
+   vrh = kzalloc(sizeof(*vrh), GFP_KERNEL);
+   if (!vrh)
+   return NULL;
+
+   err = rproc_alloc_vring(rvdev, index);
+   if (err)
+   goto free_vring;
+
+
+   rvring = &rvdev->vring[index];
+   /* zero vring */
+   memset(rvring->va, 0, vring_size(rvring->len, rvring->align));
+   vring_init(&vrh->vring, rvring->len, rvring->va, rvring->align);
+
+   rvring->vringh_cb = cb;
+   rvring->vringh = vrh;
+
+   err = vringh_init_kern(vrh,
+  rvdev->dfeatures,
+  rvring->len,
+  false,
+  vrh->vring.desc,
+  vrh->vring.

[PATCHv2 vringh 0/3] Introduce CAIF Virtio driver

2013-02-12 Thread sjur . brandeland
From: Sjur Brændeland 

This driver depends on Rusty's new host virtio ring implementation,
so this patch-set is based on the vringh branch in Rusty's git.

Changes since V1:
- Use the new iov helper functions, and simplify iov handling.
  However this triggers compile warnings, as it takes struct iov
  while kernel api uses struct kiov
- Introduced the module_virtio_driver macro
- Pass NULL as wiov to vringh_getdesc_kern() 

Regards,
Sjur

Sjur Brændeland (2):
  remoteproc: Add support for vringh (Host vrings)
  virtio: Add module driver macro for virtio drivers.

Vikram ARV (1):
  caif_virtio: Introduce caif over virtio

 drivers/net/caif/Kconfig   |8 +
 drivers/net/caif/Makefile  |3 +
 drivers/net/caif/caif_virtio.c |  547 
 drivers/remoteproc/Kconfig |3 +
 drivers/remoteproc/remoteproc_virtio.c |  127 +++-
 include/linux/remoteproc.h |   14 +
 include/linux/virtio.h |9 +
 include/linux/virtio_caif.h|   24 ++
 include/uapi/linux/virtio_ids.h|1 +
 9 files changed, 729 insertions(+), 7 deletions(-)
 create mode 100644 drivers/net/caif/caif_virtio.c
 create mode 100644 include/linux/virtio_caif.h

-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCH] virtio: Add module driver macro for virtio drivers.

2013-02-11 Thread sjur . brandeland
From: Sjur Brændeland 

Add helper macro for drivers that don't do anything
special in module init/exit.

Signed-off-by: Sjur Brændeland 
---
Hi Rusty,

Here is the patch for module driver macro.
I will update caif_virtio accordingly
in my next patch-set.

Thanks,
Sjur

 include/linux/virtio.h |9 +
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index cf8adb1..00ccc40 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -126,4 +126,13 @@ static inline struct virtio_driver *drv_to_virtio(struct 
device_driver *drv)
 
 int register_virtio_driver(struct virtio_driver *drv);
 void unregister_virtio_driver(struct virtio_driver *drv);
+
+/* module_virtio_driver() - Helper macro for drivers that don't do
+ * anything special in module init/exit.  This eliminates a lot of
+ * boilerplate.  Each module may only use this macro once, and
+ * calling it replaces module_init() and module_exit()
+ */
+#define module_virtio_driver(__virtio_driver) \
+   module_driver(__virtio_driver, register_virtio_driver, \
+   unregister_virtio_driver)
 #endif /* _LINUX_VIRTIO_H */
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCH vringh 2/2] caif_virtio: Introduce caif over virtio

2013-02-10 Thread sjur . brandeland
From: Vikram ARV 

Add the the Virtio shared memory driver for STE Modems.
caif_virtio is implemented utilizing the virtio framework
for data transport and is managed with the remoteproc frameworks.

The Virtio queue is used for transmitting data to the modem, and
the new vringh implementation is receiving data over the vring.

Signed-off-by: Vikram ARV 
Signed-off-by: Sjur Brændeland 

to: David S. Miller 
cc: Rusty Russell 
cc: Ohad Ben-Cohen 
cc: Ido Yariv 
cc: Erwan Yvin 
---
Hi Dave,

Rusty has accepted to take this patch via his tree.
Feedback and review comments are appreciated.

Thanks,
Sjur

 drivers/net/caif/Kconfig|8 +
 drivers/net/caif/Makefile   |3 +
 drivers/net/caif/caif_virtio.c  |  568 +++
 include/linux/virtio_caif.h |   24 ++
 include/uapi/linux/virtio_ids.h |1 +
 5 files changed, 604 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/caif/caif_virtio.c
 create mode 100644 include/linux/virtio_caif.h

diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig
index abf4d7a..a8b67e9 100644
--- a/drivers/net/caif/Kconfig
+++ b/drivers/net/caif/Kconfig
@@ -47,3 +47,11 @@ config CAIF_HSI
The caif low level driver for CAIF over HSI.
Be aware that if you enable this then you also need to
enable a low-level HSI driver.
+
+config CAIF_VIRTIO
+   tristate "CAIF virtio transport driver"
+   depends on CAIF
+   depends on REMOTEPROC
+   default n
+   ---help---
+   The caif driver for CAIF over Virtio.
diff --git a/drivers/net/caif/Makefile b/drivers/net/caif/Makefile
index 91dff86..d9ee26a 100644
--- a/drivers/net/caif/Makefile
+++ b/drivers/net/caif/Makefile
@@ -13,3 +13,6 @@ obj-$(CONFIG_CAIF_SHM) += caif_shm.o
 
 # HSI interface
 obj-$(CONFIG_CAIF_HSI) += caif_hsi.o
+
+# Virtio interface
+obj-$(CONFIG_CAIF_VIRTIO) += caif_virtio.o
diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c
new file mode 100644
index 000..e8ea114
--- /dev/null
+++ b/drivers/net/caif/caif_virtio.c
@@ -0,0 +1,568 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2012
+ * Contact: Sjur Brendeland / sjur.brandel...@stericsson.com
+ * Authors: Vicram Arv / vikram@stericsson.com,
+ * Dmitry Tarnyagin / dmitry.tarnya...@stericsson.com
+ * Sjur Brendeland / sjur.brandel...@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Vicram Arv ");
+MODULE_AUTHOR("Sjur Brendeland riov.allocated) {
+   kfree(ctx->riov.iov);
+   ctx->riov.iov = NULL;
+   ctx->riov.allocated = false;
+   }
+   ctx->riov.iov = NULL;
+   ctx->riov.i = 0;
+   ctx->riov.max = 0;
+}
+
+static void cfv_release_cb(struct virtqueue *vq_tx)
+{
+   struct cfv_info *cfv = vq_tx->vdev->priv;
+   tasklet_schedule(&cfv->tx_release_tasklet);
+}
+
+/* This is invoked whenever the remote processor completed processing
+ * a TX msg we just sent it, and the buffer is put back to the used ring.
+ */
+static void cfv_release_used_buf(struct virtqueue *vq_tx)
+{
+   struct cfv_info *cfv = vq_tx->vdev->priv;
+   unsigned long flags;
+
+   BUG_ON(vq_tx != cfv->vq_tx);
+   WARN_ON_ONCE(irqs_disabled());
+
+   for (;;) {
+   unsigned int len;
+   struct token_info *buf_info;
+
+   /* Get used buffer from used ring to recycle used descriptors */
+   spin_lock_irqsave(&cfv->tx_lock, flags);
+   buf_info = virtqueue_get_buf(vq_tx, &len);
+
+   if (!buf_info)
+   goto out;
+
+   BUG_ON(!cfv->queued_tx);
+   if (--cfv->queued_tx <= cfv->watermark_tx) {
+   cfv->watermark_tx = 0;
+   netif_tx_wake_all_queues(cfv->ndev);
+   }
+   spin_unlock_irqrestore(&cfv->tx_lock, flags);
+
+   dma_free_coherent(vq_tx->vdev->dev.parent->parent,
+ buf_info->size, buf_info->vaddr,
+ buf_info->dma_handle);
+   kfree(buf_info);
+   }
+   return;
+out:
+   spin_unlock_irqrestore(&cfv->tx_lock, flags);
+}
+
+static struct sk_buff *cfv_alloc_and_copy_skb(int *err,
+ struct cfv_info *cfv,
+ u8 *frm, u32 frm_len)
+{
+   struct sk_buff *skb;
+   u32 cfpkt_len, pad_len;
+
+   *err = 0;
+   /* Verify that packet size with down-link header and mtu size */
+   if (frm_len > cfv->mru || frm_len <= cfv->rx_hr + cfv->rx_tr) {
+   netdev_err(cfv->ndev,
+  "Invalid frmlen:%u  mtu:%u hr:%d tr:%d\n",
+  frm_len, cfv->mru,  c

[PATCH vringh 1/2] remoteproc: Add support for vringh (Host vrings)

2013-02-10 Thread sjur . brandeland
From: Sjur Brændeland 

Add functions for creating, deleting and kicking host-side virtio rings.

The host ring is not integrated with virtiqueues and cannot be managed
through virtio-config. Remoteproc must export functions for handling the
host-side virtio rings.

The functions rproc_virtio_get_vringh(), rproc_virtio_del_vringh(),
rproc_virtio_kick_vringh() are added to remoteproc_virtio.c. The
existing functions rproc_vq_interrupt() and rproc_virtio_find_vqs()
are updated to handle the new vhost rings.

Signed-off-by: Sjur Brændeland 
cc: Ohad Ben-Cohen 
cc: Rusty Russell 
cc: Ido Yariv 
cc: Erwan Yvin 

---
Hi Ohad,

I would really appreciate if you could find time to
review this patch. It will go via Rusty's vringh tree.

Feedback and review comments are welcomed.

Thanks,
Sjur


 drivers/remoteproc/Kconfig |3 +
 drivers/remoteproc/remoteproc_virtio.c |  127 ++--
 include/linux/remoteproc.h |   14 
 3 files changed, 137 insertions(+), 7 deletions(-)

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 96ce101..c7d1d36 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -7,6 +7,9 @@ config REMOTEPROC
depends on HAS_DMA
select FW_CONFIG
select VIRTIO
+   select VHOST_RING
+
+source drivers/vhost/Kconfig
 
 config OMAP_REMOTEPROC
tristate "OMAP remoteproc support"
diff --git a/drivers/remoteproc/remoteproc_virtio.c 
b/drivers/remoteproc/remoteproc_virtio.c
index 9e198e5..fa7bf7b 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -60,10 +61,15 @@ irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int 
notifyid)
dev_dbg(&rproc->dev, "vq index %d is interrupted\n", notifyid);
 
rvring = idr_find(&rproc->notifyids, notifyid);
-   if (!rvring || !rvring->vq)
+   if (!rvring)
return IRQ_NONE;
 
-   return vring_interrupt(0, rvring->vq);
+   if (rvring->vringh && rvring->vringh_cb)
+   return rvring->vringh_cb(&rvring->rvdev->vdev, rvring->vringh);
+   else if (rvring->vq)
+   return vring_interrupt(0, rvring->vq);
+   else
+   return IRQ_NONE;
 }
 EXPORT_SYMBOL(rproc_vq_interrupt);
 
@@ -149,14 +155,21 @@ static int rproc_virtio_find_vqs(struct virtio_device 
*vdev, unsigned nvqs,
   const char *names[])
 {
struct rproc *rproc = vdev_to_rproc(vdev);
-   int i, ret;
+   struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
+   int rng, id, ret, nrings = ARRAY_SIZE(rvdev->vring);
+
+   for (id = 0, rng = 0; rng < nrings; ++rng) {
+   struct rproc_vring *rvring = &rvdev->vring[rng];
+   /* Skip the host side rings */
+   if (rvring->vringh)
+   continue;
 
-   for (i = 0; i < nvqs; ++i) {
-   vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i]);
-   if (IS_ERR(vqs[i])) {
-   ret = PTR_ERR(vqs[i]);
+   vqs[id] = rp_find_vq(vdev, rng, callbacks[id], names[id]);
+   if (IS_ERR(vqs[id])) {
+   ret = PTR_ERR(vqs[id]);
goto error;
}
+   ++id;
}
 
/* now that the vqs are all set, boot the remote processor */
@@ -173,6 +186,106 @@ error:
return ret;
 }
 
+/**
+ * rproc_virtio_new_vringh() - create a reversed virtio ring.
+ * @vdev: the virtio device
+ * @index: the virtio ring index
+ * @cb: callback for the reversed virtio ring
+ *
+ * This function should be called by the virtio-driver
+ * before calling find_vqs(). It returns a struct vringh for
+ * accessing the virtio ring.
+ *
+ * Return: struct vhost, or NULL upon error.
+ */
+struct vringh *
+rproc_virtio_new_vringh(struct virtio_device *vdev, unsigned index,
+   irqreturn_t (*cb)(struct virtio_device *vdev,
+ struct vringh *vring))
+{
+   struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
+   struct rproc_vring *rvring;
+   struct vringh *vrh;
+   int err;
+
+   if (index > ARRAY_SIZE(rvdev->vring)) {
+   dev_err(&rvdev->vdev.dev, "bad vring index: %d\n", index);
+   return NULL;
+   }
+
+   vrh = kzalloc(sizeof(*vrh), GFP_KERNEL);
+   if (!vrh)
+   return NULL;
+
+   err = rproc_alloc_vring(rvdev, index);
+   if (err)
+   goto free_vring;
+
+
+   rvring = &rvdev->vring[index];
+   /* zero vring */
+   memset(rvring->va, 0, vring_size(rvring->len, rvring->align));
+   vring_init(&vrh->vring, rvring->len, rvring->va, rvring->align);
+
+   rvring->vringh_cb = cb;
+   rvring->vringh = vrh;
+
+   err = vringh_init_kern(vrh,
+  rvdev->dfeat

[PATCH vringh 0/2] Introduce CAIF Virtio driver

2013-02-10 Thread sjur . brandeland
From: Sjur Brændeland 

This patch-set introduces the CAIF Virtio Link layer driver.

This driver depends on Rusty's new host virtio ring implementation,
so this patch-set is based on the vringh branch in Rusty's git.

Regards,
Sjur

cc: Rusty Russell 
cc: Ohad Ben-Cohen 
cc: David S. Miller 
cc: Ido Yariv 
cc: Erwan Yvin 

Sjur Brændeland (1):
  remoteproc: Add support for vringh (Host vrings)

Vikram ARV (1):
  caif_virtio: Introduce caif over virtio

 drivers/net/caif/Kconfig   |8 +
 drivers/net/caif/Makefile  |3 +
 drivers/net/caif/caif_virtio.c |  568 
 drivers/remoteproc/Kconfig |3 +
 drivers/remoteproc/remoteproc_virtio.c |  127 +++-
 include/linux/remoteproc.h |   14 +
 include/linux/virtio_caif.h|   24 ++
 include/uapi/linux/virtio_ids.h|1 +
 8 files changed, 741 insertions(+), 7 deletions(-)
 create mode 100644 drivers/net/caif/caif_virtio.c
 create mode 100644 include/linux/virtio_caif.h

-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[RFC] remoteproc: Add support for host-side (reversed) vrings

2013-01-18 Thread sjur . brandeland
From: Sjur Brændeland 

Hi Ohad, Ido and Rusty.

Rusty has implemented host-side virtio ring. I will be using vringh
for the caif_virtio driver. But we need to figure out how to
integrate the vringh into remoteproc. Below is my initial stab on this.

This code is completely untested, but I'd love to get some initial
feedback on this.

Ohad/Ido are you happy with this approach?

More code will follow after some test and debugging...

Regards,
Sjur

--
remoteproc: Add support for host-side (reversed) vrings

Add functions for creating, deleting and kicking host-side virtio rings.

The host ring is not integrated with virtiqueues and cannot be managed
through virtio-config. So the virtio drivers must call functions exported
from remoteproc for handling the host-side virtio rings.

The functions rproc_virtio_get_vringh(), rproc_virtio_del_vringh(),
rproc_virtio_kick_vringh() are added to remoteproc_virtio.c. The
existing functions rproc_vq_interrupt() and rproc_virtio_find_vqs()
are updated to handle the new vhost rings.

Signed-off-by: Sjur Brændeland 
---
 drivers/remoteproc/remoteproc_virtio.c |  116 ++--
 include/linux/remoteproc.h |   14 
 2 files changed, 124 insertions(+), 6 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_virtio.c 
b/drivers/remoteproc/remoteproc_virtio.c
index 9e198e5..1928433 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -63,7 +64,10 @@ irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int 
notifyid)
if (!rvring || !rvring->vq)
return IRQ_NONE;
 
-   return vring_interrupt(0, rvring->vq);
+   if (rvring->vringh && rvring->vringh_cb)
+   return rvring->vringh_cb(&rvring->rvdev->vdev, rvring->vringh);
+   else
+   return vring_interrupt(0, rvring->vq);
 }
 EXPORT_SYMBOL(rproc_vq_interrupt);
 
@@ -149,14 +153,21 @@ static int rproc_virtio_find_vqs(struct virtio_device 
*vdev, unsigned nvqs,
   const char *names[])
 {
struct rproc *rproc = vdev_to_rproc(vdev);
-   int i, ret;
+   struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
+   int rng, id, ret, nrings = ARRAY_SIZE(rvdev->vring);
+
+   for (id = 0, rng = 0; rng < nrings; ++rng) {
+   struct rproc_vring *rvring = &rvdev->vring[rng];
+   /* Skip the host side rings */
+   if (rvring->vringh)
+   continue;
 
-   for (i = 0; i < nvqs; ++i) {
-   vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i]);
-   if (IS_ERR(vqs[i])) {
-   ret = PTR_ERR(vqs[i]);
+   vqs[id] = rp_find_vq(vdev, rng, callbacks[id], names[id]);
+   if (IS_ERR(vqs[id])) {
+   ret = PTR_ERR(vqs[id]);
goto error;
}
+   ++id;
}
 
/* now that the vqs are all set, boot the remote processor */
@@ -173,6 +184,99 @@ error:
return ret;
 }
 
+/**
+ * rproc_virtio_new_vringh() - create a reversed virtio ring.
+ * @vdev: the virtio device
+ * @index: the virtio ring index
+ * @cb: callback for the reversed virtio ring
+ *
+ * This function should be called by the virtio-driver
+ * before calling find_vqs(). It returns a struct vringh for
+ * accessing the virtio ring.
+ *
+ * Return: struct vhost, or NULL upon error.
+ */
+struct vringh *
+rproc_virtio_new_vringh(struct virtio_device *vdev, unsigned index,
+   irqreturn_t (*cb)(struct virtio_device *vdev,
+ struct vringh *vring))
+{
+   struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
+   struct rproc_vring *rvring;
+   struct vringh *vrh;
+   int err;
+
+   if (index > ARRAY_SIZE(rvdev->vring)) {
+   dev_err(&rvdev->vdev.dev, "bad vring index: %d\n", index);
+   return NULL;
+   }
+
+   vrh = kzalloc(sizeof(*vrh), GFP_KERNEL);
+   if (!vrh)
+   return NULL;
+
+
+   rvring = &rvdev->vring[index];
+   vring_init(&vrh->vring, rvring->len, rvring->va, rvring->align);
+   /* zero vring */
+   memset(&vrh->vring, 0, vring_size(rvring->len, rvring->align));
+   rvring->vringh_cb = cb;
+   rvring->vringh = vrh;
+
+   err = vringh_init_kern(vrh,
+  rvdev->dfeatures,
+  rvring->len,
+  false,
+  vrh->vring.desc,
+  vrh->vring.avail,
+  vrh->vring.used);
+   if (err) {
+   dev_err(&vdev->dev, "failed to create vhost: %d\n", err);
+   kfree(vrh);
+   vrh = NULL;
+   }
+
+   return vrh;
+}
+EXPORT_SYMBOL(rproc_virtio_get_vringh);
+
+/**
+ * rproc_virtio_del_vri

[RFC] virtio_console: Add DRIVER and INTERFACE to uevent.

2013-01-17 Thread sjur . brandeland
From: Sjur Brændeland 

Add information so rproc-serial can be easily recogniced
from user space. Add the following information to uevent:
DRIVER=virtio_console|virtio_rproc_serial
INTERFACE=grand-parent/parent/name

Signed-off-by: Sjur Brændeland 
---
Hi,

I need some way to identify the major/minor number for
the rproc-serial device, given the udev event. 
Review comments are welcomed.

Thanks,
Sjur

 drivers/char/virtio_console.c |   22 ++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 031be0b..96c5ed9 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -2190,6 +2190,27 @@ static struct virtio_driver virtio_rproc_serial = {
.remove =   virtcons_remove,
 };
 
+int class_virtio_ports_uevent(struct device *_dev, struct kobj_uevent_env *env)
+{
+   struct port *port = dev_get_drvdata(_dev);
+   struct device *dev;
+   int err;
+
+   if (!port || !port->portdev || !port->portdev->vdev)
+   return 0;
+
+   dev = &port->portdev->vdev->dev;
+   err = add_uevent_var(env, "DRIVER=%s", dev->driver->name);
+   if (err)
+   return err;
+
+   return add_uevent_var(env, "INTERFACE=%s/%s/%s",
+ dev->parent->parent ?
+   dev_name(dev->parent->parent) : "",
+ dev->parent ? dev_name(dev->parent) : "",
+ dev_name(dev));
+}
+
 static int __init init(void)
 {
int err;
@@ -2201,6 +,7 @@ static int __init init(void)
return err;
}
 
+   pdrvdata.class->dev_uevent = class_virtio_ports_uevent;
pdrvdata.debugfs_dir = debugfs_create_dir("virtio-ports", NULL);
if (!pdrvdata.debugfs_dir) {
pr_warning("Error %ld creating debugfs dir for virtio-ports\n",
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCH] virtio_console: Use virtio device index to generate port name

2013-01-17 Thread sjur . brandeland
From: Sjur Brændeland 

Use virtio device index for creating unique device port names.
Current index allocation in virtio is based on a monotonically
increasing variable "index". A better handling of this is to
use device index which is allocated by ida.

Signed-off-by: Sjur Brændeland 
---
 drivers/char/virtio_console.c |   16 +++-
 1 files changed, 3 insertions(+), 13 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index c17b053..031be0b 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -61,9 +61,6 @@ struct ports_driver_data {
/* List of all the devices we're handling */
struct list_head portdevs;
 
-   /* Number of devices this driver is handling */
-   unsigned int index;
-
/*
 * This is used to keep track of the number of hvc consoles
 * spawned by this driver.  This number is given as the first
@@ -169,9 +166,6 @@ struct ports_device {
/* Array of per-port IO virtqueues */
struct virtqueue **in_vqs, **out_vqs;
 
-   /* Used for numbering devices for sysfs and debugfs */
-   unsigned int drv_index;
-
/* Major number for this device.  Ports will be created as minors. */
int chr_major;
 };
@@ -1415,7 +1409,7 @@ static int add_port(struct ports_device *portdev, u32 id)
}
port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev,
  devt, port, "vport%up%u",
- port->portdev->drv_index, id);
+ port->portdev->vdev->index, id);
if (IS_ERR(port->dev)) {
err = PTR_ERR(port->dev);
dev_err(&port->portdev->vdev->dev,
@@ -1470,7 +1464,7 @@ static int add_port(struct ports_device *portdev, u32 id)
 * inspect a port's state at any time
 */
sprintf(debugfs_name, "vport%up%u",
-   port->portdev->drv_index, id);
+   port->portdev->vdev->index, id);
port->debugfs_file = debugfs_create_file(debugfs_name, 0444,
 pdrvdata.debugfs_dir,
 port,
@@ -1961,16 +1955,12 @@ static int virtcons_probe(struct virtio_device *vdev)
portdev->vdev = vdev;
vdev->priv = portdev;
 
-   spin_lock_irq(&pdrvdata_lock);
-   portdev->drv_index = pdrvdata.index++;
-   spin_unlock_irq(&pdrvdata_lock);
-
portdev->chr_major = register_chrdev(0, "virtio-portsdev",
 &portdev_fops);
if (portdev->chr_major < 0) {
dev_err(&vdev->dev,
"Error %d registering chrdev for device %u\n",
-   portdev->chr_major, portdev->drv_index);
+   portdev->chr_major, vdev->index);
err = portdev->chr_major;
goto free;
}
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCH] virtio_console: Let unconnected rproc device receive data.

2013-01-17 Thread sjur . brandeland
From: Sjur Brændeland 

Allow rproc serial ports to receive data before the port
is connected.

Rproc serial ports usually talk to very simple remote devices
with no control queue managing open/close events. So we must
let remote devices write to the virtio ring even if the device
is not yet fully initialized.

Signed-off-by: Sjur Brændeland 
---

This patch is intended for v3.9.

Thanks,
Sjur

 drivers/char/virtio_console.c |5 -
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index ee4dbea..c17b053 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1763,8 +1763,11 @@ static void in_intr(struct virtqueue *vq)
 * tty is spawned) and the host sends out data to console
 * ports.  For generic serial ports, the host won't
 * (shouldn't) send data till the guest is connected.
+* However a remote device might send data before the port is
+* connected. So don't remove data from a rproc_serial device.
 */
-   if (!port->guest_connected)
+
+   if (!port->guest_connected && !is_rproc_serial(port->portdev->vdev))
discard_port_data(port);
 
spin_unlock_irqrestore(&port->inbuf_lock, flags);
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCH] virtio_console: Don't access uninitialized data.

2013-01-17 Thread sjur . brandeland
From: Sjur Brændeland 

Don't access uninitialized work-queue when removing device.
The work queue is initialized only if the device multi-queue.
So don't call cancel_work unless this is a multi-queue device.

This fixes the following panic:

Kernel panic - not syncing: BUG!
Call Trace:
62031b28:  [<6026085d>] panic+0x16b/0x2d3
62031b30:  [<6004ef5e>] flush_work+0x0/0x1d7
62031b60:  [<602606f2>] panic+0x0/0x2d3
62031b68:  [<600333b0>] memcpy+0x0/0x140
62031b80:  [<6002d58a>] unblock_signals+0x0/0x84
62031ba0:  [<602609c5>] printk+0x0/0xa0
62031bd8:  [<60264e51>] __mutex_unlock_slowpath+0x13d/0x148
62031c10:  [<6004ef5e>] flush_work+0x0/0x1d7
62031c18:  [<60050234>] try_to_grab_pending+0x0/0x17e
62031c38:  [<6004e984>] get_work_gcwq+0x71/0x8f
62031c48:  [<60050539>] __cancel_work_timer+0x5b/0x115
62031c78:  [<628acc85>] unplug_port+0x0/0x191 [virtio_console]
62031c98:  [<6005061c>] cancel_work_sync+0x12/0x14
62031ca8:  [<628ace96>] virtcons_remove+0x80/0x15c [virtio_console]
62031ce8:  [<628191de>] virtio_dev_remove+0x1e/0x7e [virtio]
62031d08:  [<601cf242>] __device_release_driver+0x75/0xe4
62031d28:  [<601cf2dd>] device_release_driver+0x2c/0x40
62031d48:  [<601ce0dd>] driver_unbind+0x7d/0xc6
62031d88:  [<601cd5d9>] drv_attr_store+0x27/0x29
62031d98:  [<60115f61>] sysfs_write_file+0x100/0x14d
62031df8:  [<600b737d>] vfs_write+0xcb/0x184
62031e08:  [<600b58b8>] filp_close+0x88/0x94
62031e38:  [<600b7686>] sys_write+0x59/0x88
62031e88:  [<6001ced1>] handle_syscall+0x5d/0x80
62031ea8:  [<60030a74>] userspace+0x405/0x531
62031f08:  [<600d32cc>] sys_dup+0x0/0x5e
62031f28:  [<601b11d6>] strcpy+0x0/0x18
62031f38:  [<600be46c>] do_execve+0x10/0x12
62031f48:  [<600184c7>] run_init_process+0x43/0x45
62031fd8:  [<60019a91>] new_thread_handler+0xba/0xbc

Signed-off-by: Sjur Brændeland 
---

This fix is intended of v3.8.

Thanks,
Sjur

 drivers/char/virtio_console.c |3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 684b0d5..ee4dbea 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -2062,7 +2062,8 @@ static void virtcons_remove(struct virtio_device *vdev)
/* Disable interrupts for vqs */
vdev->config->reset(vdev);
/* Finish up work that's lined up */
-   cancel_work_sync(&portdev->control_work);
+   if (use_multiport(portdev))
+   cancel_work_sync(&portdev->control_work);
 
list_for_each_entry_safe(port, port2, &portdev->ports, list)
unplug_port(port);
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCH resend] virtio_console: Free buffers from out-queue upon close

2012-11-07 Thread sjur . brandeland
From: Sjur Brændeland 

Free pending output buffers from the virtio out-queue when
host has acknowledged port_close. Also removed WARN_ON()
in remove_port_data().

Signed-off-by: Sjur Brændeland 
---

Resending, this time including a proper "Subject"...
--

Hi Amit,

Note: This patch is compile tested only. I have done the removal
of buffers from out-queue in handle_control_message()
when host has acked the close request. This seems less
racy than doing it in the release function.

I you want to change this further, feel free to take over from
here and refine this.

Thanks,
Sjur

 drivers/char/virtio_console.c |   14 ++
 1 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 3fa036a..3a5831d 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1522,15 +1522,9 @@ static void remove_port_data(struct port *port)
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 pending buffers from the out-queue. */
+   while ((buf = virtqueue_detach_unused_buf(port->out_vq)))
free_buf(buf, true);
-   }
 }
 
 /*
@@ -1655,6 +1649,10 @@ static void handle_control_message(struct ports_device 
*portdev,
 */
spin_lock_irq(&port->outvq_lock);
reclaim_consumed_buffers(port);
+
+   /* Free pending buffers from the out-queue. */
+   while ((buf = virtqueue_detach_unused_buf(port->out_vq)))
+   free_buf(buf, true);
spin_unlock_irq(&port->outvq_lock);
 
/*
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[no subject]

2012-11-07 Thread sjur . brandeland
From 0ce16d6a0270daebd9972e94a834034a093228b0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sjur=20Br=C3=A6ndeland?= 
Date: Wed, 7 Nov 2012 12:20:07 +0100
Subject: [PATCH] virtio_console:Free buffers from out-queue upon close
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Free pending output buffers from the virtio out-queue when
host has acknowledged port_close. Also removed WARN_ON()
in remove_port_data().

Signed-off-by: Sjur Brændeland 
---
Hi Amit,

Note: This patch is compile tested only. I have done the removal
of buffers from out-queue in handle_control_message()
when host has acked the close request. This seems less
racy than doing it in the release function.

I you want to change this further, feel free to take over from
here and refine this.

Thanks,
Sjur

 drivers/char/virtio_console.c |   14 ++
 1 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 3fa036a..3a5831d 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1522,15 +1522,9 @@ static void remove_port_data(struct port *port)
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 pending buffers from the out-queue. */
+   while ((buf = virtqueue_detach_unused_buf(port->out_vq)))
free_buf(buf, true);
-   }
 }
 
 /*
@@ -1655,6 +1649,10 @@ static void handle_control_message(struct ports_device 
*portdev,
 */
spin_lock_irq(&port->outvq_lock);
reclaim_consumed_buffers(port);
+
+   /* Free pending buffers from the out-queue. */
+   while ((buf = virtqueue_detach_unused_buf(port->out_vq)))
+   free_buf(buf, true);
spin_unlock_irq(&port->outvq_lock);
 
/*
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCHv7 4/4] virtio_console: Add support for remoteproc serial

2012-10-15 Thread sjur . brandeland
From: Sjur Brændeland 

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 
---
 drivers/char/virtio_console.c |  201 -
 include/linux/virtio_ids.h|1 +
 2 files changed, 180 insertions(+), 22 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 917cc830..eeb9b35 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -37,8 +37,12 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #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,58 @@ 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;
 
+   if (is_rproc_serial(vq->vdev))
+   reclaim_dma_bufs();
+
/*
 * Allocate buffer and the sg list. The sg list array is allocated
 * directly after the port_buffer struct.
@@ -373,11 +437,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

[PATCHv7 3/4] virtio_console: Merge struct buffer_token into struct port_buffer

2012-10-15 Thread sjur . brandeland
From: Sjur Brændeland 

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 
---
 drivers/char/virtio_console.c |  131 +
 1 files changed, 55 insertions(+), 76 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 301d17e..917cc830 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;
ssize_t ret;
@@ -534,7 +536,7 @@ static ssize_t __send_to_port(struct port *port, struct 
scatterlist *sg,
 
reclaim_consumed_buffers(port);
 
-   ret = virtqueue_add_buf(out_vq, sg, nents, 0, tok, GFP_ATOMIC);
+   ret = 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(si

[PATCHv7 2/4] virtio_console: Use kmalloc instead of kzalloc

2012-10-15 Thread sjur . brandeland
From: Sjur Brændeland 

Avoid the more cpu expensive kzalloc when allocating buffers.
Originally kzalloc was intended for isolating the guest from
the host by not sending random guest data to the host. But device
isolation is not yet in place so kzalloc is not really needed.

Signed-off-by: Sjur Brændeland 
---
 drivers/char/virtio_console.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index c36b2f6..301d17e 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -349,7 +349,7 @@ static struct port_buffer *alloc_buf(size_t buf_size)
buf = kmalloc(sizeof(*buf), GFP_KERNEL);
if (!buf)
goto fail;
-   buf->buf = kzalloc(buf_size, GFP_KERNEL);
+   buf->buf = kmalloc(buf_size, GFP_KERNEL);
if (!buf->buf)
goto free_buf;
buf->len = 0;
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCHv7 1/4] virtio_console: Free buffer if splice fails

2012-10-15 Thread sjur . brandeland
From: Sjur Brændeland 

Free the allocated scatter list if send_pages fails in function
port_splice_write.

Signed-off-by: Sjur Brændeland 
---
 drivers/char/virtio_console.c |2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 8ab9c3d..c36b2f6 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -879,6 +879,8 @@ static ssize_t port_fops_splice_write(struct 
pipe_inode_info *pipe,
if (likely(ret > 0))
ret = send_pages(port, sgl.sg, sgl.n, sgl.len, true);
 
+   if (unlikely(ret <= 0))
+   kfree(sgl.sg);
return ret;
 }
 
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCHv7 0/4] virtio_console: Add rproc_serial driver

2012-10-15 Thread sjur . brandeland
From: Sjur Brændeland 

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.

This patch-set is a rework of the patch-set from Sept 25th, hopefully all
review comments has been addressed.

The fist patch is a bugfix and migth be applicable for 3.7.

Thanks,
Sjur

Sjur Brændeland (4):
  virtio_console: Free buffer if splice fails
  virtio_console: Use kmalloc instead of kzalloc
  virtio_console: Merge struct buffer_token into struct port_buffer
  virtio_console: Add support for remoteproc serial

 drivers/char/virtio_console.c |  328 +
 include/linux/virtio_ids.h|1 +
 2 files changed, 234 insertions(+), 95 deletions(-)

-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCH 3/3] virtio_console: Don't initialize buffers to zero

2012-09-25 Thread sjur . brandeland
From: Sjur Brændeland 

Skip initializing the receive buffers.

Signed-off-by: Sjur Brændeland 
---
 drivers/char/virtio_console.c |1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index faedd2c..e7d8787 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1344,7 +1344,6 @@ static unsigned int fill_queue(struct virtqueue *vq, 
spinlock_t *lock)
if (!buf)
break;
 
-   memset(buf->buf, 0, PAGE_SIZE);
spin_lock_irq(lock);
ret = add_inbuf(vq, buf);
if (ret < 0) {
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCHv5 2/3] virtio_console: Add support for remoteproc serial

2012-09-25 Thread sjur . brandeland
From: Sjur Brændeland 

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 
cc: Rusty Russell 
cc: Michael S. Tsirkin 
cc: Amit Shah 
cc: Ohad Ben-Cohen 
cc: Linus Walleij 
cc: Arnd Bergmann 
---
Changes since v4:
- New baseline
- Use name is_rproc_enabled
- Renamed list and spin-lock used for pending deletion of dma buffers
- Minor style fixes: indentation, removed brace


 drivers/char/virtio_console.c |  184 +
 include/linux/virtio_ids.h|1 +
 2 files changed, 170 insertions(+), 15 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index f4f7b04..faedd2c 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -37,8 +37,12 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #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, else sg is used */
unsigned int sgpages;
 
@@ -330,6 +343,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)
 {
/*
@@ -341,32 +359,84 @@ static inline bool use_multiport(struct ports_device 
*portdev)
return portdev->vdev->features[0] & (1 << VIRTIO_CONSOLE_F_MULTIPORT);
 }
 
+static DEFINE_SPINLOCK(dma_bufs_lock);
+static LIST_HEAD(pending_free_dma_bufs);
+
 static void free_buf(struct port_buffer *buf)
 {
int i;
+   unsigned long flags;
 
-   kfree(buf->buf);
+   if (!buf->dev)
+   kfree(buf->buf);
 
-   if (buf->sgpages)
+   if (buf->sgpages) {
for (i = 0; i < buf->sgpages; i++) {
struct page *page = sg_page(&buf->sg[i]);
if (!page)
break;
put_page(page);
}
+   return;
+   }
+
+   if (buf->dev && is_rproc_enabled) {
+
+   /* dma_free_coherent requires interrupts to be enabled. */
+   if (irqs_disabled()) {
+   /* 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 */
+   might_sleep();
+   put_device(buf->dev);
+   }
 
kfree(buf);
 }
 
+static void reclaim_dma_bufs(void)
+{
+   unsigned long flags;
+   struct port_buffer *buf, *tmp;
+   LIST_HEAD(tmp_list);
+
+   WARN_ON(irqs_disabled());
+   if (list_empty(&pending_free_dma_bufs))
+   return;
+
+   BUG_ON(!is_rproc_enabled);
+
+   /* 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);
+   }
+}
+
 static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size,
 int nrbufs)
 {
struct port_buffer *buf;
size_t alloc_size;
 
+   if (is_rproc_serial(vq->vdev) && !irqs_disabled())
+   reclaim_dma_bufs();
+
/* Allocate buffer and the scatter list */
alloc_size = sizeof(*buf) + sizeof(struct scatterlist) * nrbufs;
-   buf = kmalloc(alloc_size, GFP_ATOMIC);
+   buf = kzalloc(alloc_size, GFP_ATOMIC);
if (!buf)
goto fail;
 
@@ -374,11 +444,30 @@ static struct port_bu

[PATCH 1/3] virtio_console:Merge struct buffer_token into struct port_buffer

2012-09-25 Thread sjur . brandeland
From: Sjur Brændeland 

This merge reduces code size by unifying the approach for
sending scatter-lists and regular buffers. Any type of
write operation (splice, write, put_chars) will now allocate
a port_buffer and send_buf() and free_buf() can always be used.

Signed-off-by: Sjur Brændeland 
cc: Rusty Russell 
cc: Michael S. Tsirkin 
cc: Amit Shah 
cc: Linus Walleij 
cc: Masami Hiramatsu 
---
 drivers/char/virtio_console.c |  141 ++---
 1 files changed, 62 insertions(+), 79 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 8ab9c3d..f4f7b04 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -111,6 +111,11 @@ 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, else sg is used */
+   unsigned int sgpages;
+
+   struct scatterlist sg[1];
 };
 
 /*
@@ -338,23 +343,46 @@ static inline bool use_multiport(struct ports_device 
*portdev)
 
 static void free_buf(struct port_buffer *buf)
 {
+   int i;
+
kfree(buf->buf);
+
+   if (buf->sgpages)
+   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 nrbufs)
 {
struct port_buffer *buf;
+   size_t alloc_size;
 
-   buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+   /* Allocate buffer and the scatter list */
+   alloc_size = sizeof(*buf) + sizeof(struct scatterlist) * nrbufs;
+   buf = kmalloc(alloc_size, GFP_ATOMIC);
if (!buf)
goto fail;
-   buf->buf = kzalloc(buf_size, GFP_KERNEL);
+
+   buf->sgpages = nrbufs;
+   if (nrbufs > 0)
+   return buf;
+
+   buf->buf = kmalloc(buf_size, GFP_ATOMIC);
if (!buf->buf)
goto free_buf;
buf->len = 0;
buf->offset = 0;
buf->size = buf_size;
+
+   /* Prepare scatter buffer for sending */
+   sg_init_one(buf->sg, buf->buf, buf_size);
return buf;
 
 free_buf:
@@ -476,52 +504,25 @@ 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)
+static ssize_t send_buf(struct port *port, struct port_buffer *buf, int nents,
+ size_t in_count, bool nonblock)
 {
struct virtqueue *out_vq;
ssize_t ret;
@@ -534,7 +535,7 @@ static ssize_t __send_to_port(struct port *port, struct 
scatterlist *sg,
 
reclaim_consumed_buffers(port);
 
-   ret = virtqueue_add_buf(out_vq, sg, nents, 0, tok, GFP_ATOMIC);
+   ret = virtqueue_add_buf(out_vq, buf->sg, nents, 0, buf, GFP_ATOMIC);
 
/* Tell Host to go! */
virtqueue_kick(out_vq);
@@ -559,8 +560,11 @@ static ssize_t __send_to_port(struct port *port, struct 
scatterlist *sg,
 * we need to kmalloc a GFP_ATOMIC buffer each time the
 * console driver writes something out.
 */
-   while (!virtqueue_get_buf(out_vq, &len))
+   for (buf = virtqueue_get_buf(out_vq, &len); !buf;
+buf = virtqueue_get_buf(out_vq, &len))
  

[PATCHv6 0/3] virtio_console: Add rproc_serial device

2012-09-25 Thread sjur . brandeland
From: Sjur Brændeland 

I thought rebasing rproc_serial to linux-next was going to be trivial.
But when starting the merge I realized that I had to refactor the
the patches from  Masami Hiramatsu. The splice support has the same issue
as I faced, with different type of buffers in the out_vq.
So I ended up refactoring the splice functionality. The code
size got smaller so hopefully this a step in the right direction.

This refactoring also make introduction of rproc_serial cleaner.

As requested I also added a patch for not initializing buffers.

I have tested the VIRTIO_CONSOLE device by looping large amount of data
through character device and tty, with lockdep and slub-debug on.
This looks stable for me. I've also done a simple test of splice.

Thanks,
Sjur

cc: Rusty Russell 
cc: Michael S. Tsirkin 
cc: Amit Shah 
cc: Linus Walleij 
cc: Masami Hiramatsu 


Sjur Brændeland (3):
  virtio_console:Merge struct buffer_token into struct port_buffer
  virtio_console: Add support for remoteproc serial
  virtio_console: Don't initialize buffers to zero

 drivers/char/virtio_console.c |  318 +
 include/linux/virtio_ids.h|1 +
 2 files changed, 228 insertions(+), 91 deletions(-)

-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCHv4] virtio_console: Add support for remoteproc serial

2012-09-24 Thread sjur . brandeland
From: Sjur Brændeland 

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 
cc: Rusty Russell 
cc: Michael S. Tsirkin 
cc: Amit Shah 
cc: Ohad Ben-Cohen 
cc: Linus Walleij 
cc: Arnd Bergmann 
---

Changes since v3 are mostly related to freeing of dma-buffers:
- Change port_fops_write() to use struct port_buffer when allocating
  memory. This is done in order to store the dma-address of the
  allocated buffers, so the correct dma-address can be passed to
  dma_free_coherent().
- Added pending_free_list for port_buf. dma_free_coherent() requires
  the irqs to be enabled, so if irqs are disabled we queue the buffer
  on the pending_free_list and free it later when irqs are enabled.
- Remove #if around is_rproc_serial

Thanks,
Sjur

 drivers/char/virtio_console.c |  222 -
 include/linux/virtio_ids.h|1 +
 2 files changed, 199 insertions(+), 24 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index cdf2f54..3af9a5d 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -35,8 +35,12 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include "../tty/hvc/hvc_console.h"
 
+#define rproc_enabled IS_ENABLED(CONFIG_REMOTEPROC)
+
 /*
  * This is a global struct for storing common data for all the devices
  * this driver handles.
@@ -109,6 +113,15 @@ struct port_buffer {
size_t len;
/* 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;
 };
 
 /*
@@ -323,6 +336,11 @@ static bool is_console_port(struct port *port)
return false;
 }
 
+static bool is_rproc_serial(const struct virtio_device *vdev)
+{
+   return rproc_enabled && vdev->id.device == VIRTIO_ID_RPROC_SERIAL;
+}
+
 static inline bool use_multiport(struct ports_device *portdev)
 {
/*
@@ -334,20 +352,99 @@ static inline bool use_multiport(struct ports_device 
*portdev)
return portdev->vdev->features[0] & (1 << VIRTIO_CONSOLE_F_MULTIPORT);
 }
 
+static DEFINE_SPINLOCK(list_lock);
+static LIST_HEAD(pending_free_list);
+
 static void free_buf(struct port_buffer *buf)
 {
-   kfree(buf->buf);
+   unsigned long flags;
+
+   if (!buf->dev) {
+   kfree(buf->buf);
+   goto freebuf;
+   }
+
+   BUG_ON(!rproc_enabled);
+
+   /* dma_free_coherent requires interrupts to be enabled */
+   if (rproc_enabled && !irqs_disabled()) {
+   dma_free_coherent(buf->dev, buf->size, buf->buf, buf->dma);
+
+   /* Release device refcnt and allow it to be freed */
+   might_sleep();
+   put_device(buf->dev);
+   goto freebuf;
+   }
+
+   /* queue up dma-buffers to be freed later */
+   spin_lock_irqsave(&list_lock, flags);
+   list_add_tail(&buf->list, &pending_free_list);
+   spin_unlock_irqrestore(&list_lock, flags);
+   return;
+
+freebuf:
kfree(buf);
 }
 
-static struct port_buffer *alloc_buf(size_t buf_size)
+static void reclaim_dma_bufs(void)
+{
+   unsigned long flags;
+   struct port_buffer *buf, *tmp;
+   LIST_HEAD(tmp_list);
+
+   WARN_ON(irqs_disabled());
+   if (list_empty(&pending_free_list))
+   return;
+
+   BUG_ON(!rproc_enabled);
+
+   /* Create a copy of the pending_free_list while holding the lock*/
+   spin_lock_irqsave(&list_lock, flags);
+   list_cut_position(&tmp_list, &pending_free_list,
+ pending_free_list.prev);
+   spin_unlock_irqrestore(&list_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);
+   }
+}
+
+static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size)
 {
struct port_buffer *buf;
 
+   if (is_rproc_serial(vq->vdev) && !irqs_disabled())
+   reclaim_dma_bufs();
+
buf = kmalloc(sizeof(*buf), GFP_KERNEL);
if (!buf)
goto fail;
-   buf->buf = kzalloc(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.
+   

[PATCHv3] virtio_console: Add support for remoteproc serial

2012-09-20 Thread sjur . brandeland
From: Sjur Brændeland 

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.

This enables use of the exising virtio_console code in
the remoteproc framework.

Signed-off-by: Sjur Brændeland 
cc: Rusty Russell 
cc: Michael S. Tsirkin 
cc: Amit Shah 
cc: Ohad Ben-Cohen 
cc: Linus Walleij 
cc: virtualization@lists.linux-foundation.org
---
Hi Amit,

Changes since v2: Fixes for Rustys review comments. The only
"unresolved" issue (unless I missed something) is the quirky
handling of finding device grandparent when doing dma_alloc.

[Rusty wrote:]
>OK, I'll let Amit comment on the console changes, but some minor style
>comments below.

Amit, any chance that you might find time to review this?

Note: This patch is based on v3.6 so this patch is will conflict
with "virtio: console: fix error handling in init() function".
Get back to me if you want me to rebase to another baseline.

Thanks,
Sjur

 drivers/char/virtio_console.c |  185 ++--
 include/linux/virtio_ids.h|1 +
 2 files changed, 158 insertions(+), 28 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index cdf2f54..4f2f74e 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -35,6 +35,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include "../tty/hvc/hvc_console.h"
 
 /*
@@ -323,6 +325,55 @@ static bool is_console_port(struct port *port)
return false;
 }
 
+#if IS_ENABLED(CONFIG_REMOTEPROC)
+static bool is_rproc_serial(const struct virtio_device *vdev)
+{
+   return vdev->id.device == VIRTIO_ID_RPROC_SERIAL;
+}
+#else
+static bool is_rproc_serial(const struct virtio_device *vdev)
+{
+   return false;
+}
+#endif
+
+/* Allocate data buffer from DMA memory if requested */
+static void *alloc_databuf(struct virtio_device *vdev, size_t size, gfp_t flag)
+{
+   if (is_rproc_serial(vdev)) {
+   dma_addr_t dma_addr;
+   struct device *dev = &vdev->dev;
+   /*
+* 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
+*/
+   dev = dev->parent ? dev->parent : dev;
+   dev = dev->parent ? dev->parent : dev;
+   return dma_alloc_coherent(dev, size, &dma_addr, flag);
+   }
+   return kmalloc(size, flag);
+}
+
+static void free_databuf(struct virtio_device *vdev, size_t size, void *vaddr)
+{
+   if (is_rproc_serial(vdev)) {
+   struct device *dev = &vdev->dev;
+   dma_addr_t dma_addr;
+
+   dev = dev->parent ? dev->parent : dev;
+   dev = dev->parent ? dev->parent : dev;
+   dma_addr = virt_to_bus(vaddr);
+   dma_free_coherent(dev, size, vaddr, dma_addr);
+   return;
+   }
+   kfree(vaddr);
+}
+
 static inline bool use_multiport(struct ports_device *portdev)
 {
/*
@@ -334,22 +385,24 @@ 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 void free_buf(struct virtqueue *vq, struct port_buffer *buf,
+size_t buf_size)
 {
-   kfree(buf->buf);
+   free_databuf(vq->vdev, buf_size, buf->buf);
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)
 {
struct port_buffer *buf;
 
buf = kmalloc(sizeof(*buf), GFP_KERNEL);
if (!buf)
goto fail;
-   buf->buf = kzalloc(buf_size, GFP_KERNEL);
+   buf->buf = alloc_databuf(vq->vdev, buf_size, GFP_KERNEL);
if (!buf->buf)
goto free_buf;
+   memset(buf->buf, 0, buf_size);
buf->len = 0;
buf->offset = 0;
buf->size = buf_size;
@@ -414,7 +467,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(port->in_vq, buf, PAGE_SIZE);
}
port->inbuf = NULL;
buf = get_inbuf(port);
@@ -485,7 +538,7 @@ static void reclaim_consumed_buff

[PATCHv2] virtio_console: Add support for remoteproc serial

2012-09-19 Thread sjur . brandeland
From: Sjur Brændeland 

Add a simple serial connection driver called
VIRTIO_ID_RPROC_SERIAL (0xB) 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.

This enables use of the exising virtio_console code in
the remoteproc framework.

Signed-off-by: Sjur Brændeland 
cc: Michael S. Tsirkin 
cc: Amit Shah 
cc: Ohad Ben-Cohen 
cc: Linus Walleij 
---

Hi Rusty,

Changes since v1:
o Use proper macros IS_ENABLED(CONFIG_REMOTEPROC)
o Fix bug at registration of rproc_serial driver
o Always allocate PAGE_SIZE buffers for rproc_serial,
  and limit write to port_fops_write to use PAGE_SIZE.

Regards,
Sjur

 drivers/char/virtio_console.c |  160 ++---
 include/linux/virtio_ids.h|1 +
 2 files changed, 134 insertions(+), 27 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index cdf2f54..395522a 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -35,6 +35,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include "../tty/hvc/hvc_console.h"
 
 /*
@@ -323,6 +325,52 @@ static bool is_console_port(struct port *port)
return false;
 }
 
+#if IS_ENABLED(CONFIG_REMOTEPROC)
+static inline bool is_rproc_serial(struct virtio_device *vdev)
+{
+   return vdev->id.device == VIRTIO_ID_RPROC_SERIAL;
+}
+#else
+static inline bool is_rproc_serial(struct virtio_device *vdev)
+{
+   return false;
+}
+#endif
+
+/* Allocate data buffer from DMA memory if requested */
+static inline void *
+alloc_databuf(struct virtio_device *vdev, size_t size, gfp_t flag)
+{
+   if (is_rproc_serial(vdev)) {
+   dma_addr_t dma;
+   struct device *dev = &vdev->dev;
+   /*
+* Allocate DMA memory from ancestors. Finding the ancestor
+* is a bit quirky when DMA_MEMORY_INCLUDES_CHILDREN is not
+* implemented.
+*/
+   dev = dev->parent ? dev->parent : dev;
+   dev = dev->parent ? dev->parent : dev;
+   return dma_alloc_coherent(dev, size, &dma, flag);
+   }
+   return kmalloc(size, flag);
+}
+
+static inline void
+free_databuf(struct virtio_device *vdev, size_t size, void *cpu_addr)
+{
+
+   if (is_rproc_serial(vdev)) {
+   struct device *dev = &vdev->dev;
+   dma_addr_t dma_handle = virt_to_bus(cpu_addr);
+   dev = dev->parent ? dev->parent : dev;
+   dev = dev->parent ? dev->parent : dev;
+   dma_free_coherent(dev, size, cpu_addr, dma_handle);
+   return;
+   }
+   kfree(cpu_addr);
+}
+
 static inline bool use_multiport(struct ports_device *portdev)
 {
/*
@@ -334,20 +382,22 @@ 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 void
+free_buf(struct virtqueue *vq, struct port_buffer *buf, size_t buf_size)
 {
-   kfree(buf->buf);
+   free_databuf(vq->vdev, buf_size, buf->buf);
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)
 {
struct port_buffer *buf;
 
buf = kmalloc(sizeof(*buf), GFP_KERNEL);
if (!buf)
goto fail;
-   buf->buf = kzalloc(buf_size, GFP_KERNEL);
+   buf->buf = alloc_databuf(vq->vdev, buf_size, GFP_KERNEL);
+   memset(buf->buf, 0, buf_size);
if (!buf->buf)
goto free_buf;
buf->len = 0;
@@ -414,7 +464,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(port->in_vq, buf, PAGE_SIZE);
}
port->inbuf = NULL;
buf = get_inbuf(port);
@@ -485,7 +535,7 @@ static void reclaim_consumed_buffers(struct port *port)
return;
}
while ((buf = virtqueue_get_buf(port->out_vq, &len))) {
-   kfree(buf);
+   free_databuf(port->portdev->vdev, PAGE_SIZE, buf);
port->outvq_full = false;
}
 }
@@ -672,6 +722,8 @@ static ssize_t port_fops_write(struct file *filp, const 
char __user *ubuf,
char *buf;
ssize_t ret;
bool nonblock;
+   struct virtio_device *vdev;
+   size_t buf_size;
 
/* Userspace could be out to fool us */
if (!count)
@@ -694,9 +746,16 @@ static ssize_t port_fops_write(struct file *filp, const 
char __user *ubuf,
if (!port->g

[PATCH] virtio_console: Add support for remoteproc serial

2012-09-13 Thread sjur . brandeland
From: Sjur Brændeland 

Add a virtio remoteproc serial driver: VIRTIO_ID_RPROC_SERIAL (0xB)
for communicating with a remote processor in an asymmetric
multi-processing configuration.

The virtio remoteproc serial driver reuses the existing virtio_console
implementation, and adds support for DMA allocation of data buffers
but disables support for tty console, mutiple ports, and the control queue.

Signed-off-by: Sjur Brændeland 
---
cc: Rusty Russell 
cc: Michael S. Tsirkin 
cc: Amit Shah 
cc: Ohad Ben-Cohen 
cc: Linus Walleij 
cc: virtualization@lists.linux-foundation.org
cc: linux-ker...@vger.kernel.org

>Just one thing, should it depend on CONFIG_REMOTEPROC?  And have
>OMAP_REMOTEPROC depend on CONFIG_HAS_DMA (if it doesn't already).

I have changed to use CONFIG_REMOTEPROC_MODULE now. I'll send a patch
to Ohad adding an explicit dependency to HAS_DMA for remoteproc.

>PS.  I've reserved 11 for you in the latest virtio spec draft.
Ok, I'll look into updating the spec.

Thanks,
Sjur


 drivers/char/virtio_console.c |  137 +
 include/linux/virtio_ids.h|1 +
 2 files changed, 112 insertions(+), 26 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index cdf2f54..7c697ca 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -35,6 +35,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include "../tty/hvc/hvc_console.h"
 
 /*
@@ -323,6 +325,52 @@ static bool is_console_port(struct port *port)
return false;
 }
 
+#ifdef CONFIG_REMOTEPROC_MODULE
+static inline bool is_rproc_serial(struct virtio_device *vdev)
+{
+   return vdev->id.device == VIRTIO_ID_RPROC_SERIAL;
+}
+#else
+static inline bool is_rproc_serial(struct virtio_device *vdev)
+{
+   return false;
+}
+#endif
+
+/* Allocate data buffer from DMA memory if requested */
+static inline void *
+alloc_databuf(struct virtio_device *vdev, size_t size, gfp_t flag)
+{
+   if (is_rproc_serial(vdev)) {
+   dma_addr_t dma;
+   struct device *dev = &vdev->dev;
+   /*
+* Allocate DMA memory from ancestors. Finding the ancestor
+* is a bit quirky when DMA_MEMORY_INCLUDES_CHILDREN is not
+* implemented.
+*/
+   dev = dev->parent ? dev->parent : dev;
+   dev = dev->parent ? dev->parent : dev;
+   return dma_alloc_coherent(dev, size, &dma, flag);
+   }
+   return kmalloc(size, flag);
+}
+
+static inline void
+free_databuf(struct virtio_device *vdev, size_t size, void *cpu_addr)
+{
+
+   if (is_rproc_serial(vdev)) {
+   struct device *dev = &vdev->dev;
+   dma_addr_t dma_handle = virt_to_bus(cpu_addr);
+   dev = dev->parent ? dev->parent : dev;
+   dev = dev->parent ? dev->parent : dev;
+   dma_free_coherent(dev, size, cpu_addr, dma_handle);
+   return;
+   }
+   kfree(cpu_addr);
+}
+
 static inline bool use_multiport(struct ports_device *portdev)
 {
/*
@@ -334,20 +382,22 @@ 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 void
+free_buf(struct virtqueue *vq, struct port_buffer *buf, size_t buf_size)
 {
-   kfree(buf->buf);
+   free_databuf(vq->vdev, buf_size, buf->buf);
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)
 {
struct port_buffer *buf;
 
buf = kmalloc(sizeof(*buf), GFP_KERNEL);
if (!buf)
goto fail;
-   buf->buf = kzalloc(buf_size, GFP_KERNEL);
+   buf->buf = alloc_databuf(vq->vdev, buf_size, GFP_KERNEL);
+   memset(buf->buf, 0, buf_size);
if (!buf->buf)
goto free_buf;
buf->len = 0;
@@ -414,7 +464,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(port->in_vq, buf, PAGE_SIZE);
}
port->inbuf = NULL;
buf = get_inbuf(port);
@@ -485,7 +535,7 @@ static void reclaim_consumed_buffers(struct port *port)
return;
}
while ((buf = virtqueue_get_buf(port->out_vq, &len))) {
-   kfree(buf);
+   free_databuf(port->portdev->vdev, len, buf);
port->outvq_full = false;
}
 }
@@ -672,6 +722,7 @@ static ssize_t port_fops_write(struct file *filp, const 
char __user *ubuf,
char *buf;
ssize_t ret;
bool nonblock;
+   struct virtio_device *vdev;
 
/* Userspace could be out to fool u

[RFCv3] virtio_console: Add support for virtio remoteproc serial

2012-09-10 Thread sjur . brandeland
From: Sjur Brændeland 

Add a virtio remoteproc serial driver: VIRTIO_ID_RPROC_SERIAL (0xB)
for communicating with a remote processor in an asymmetric
multi-processing configuration.

The virtio remoteproc serial driver reuses the existing virtio_console
implementation, and adds support for DMA allocation of data buffers
but disables support for tty console, mutiple ports, and the control queue.

Signed-off-by: Sjur Brændeland 
cc: Rusty Russell 
cc: Michael S. Tsirkin 
cc: Amit Shah 
cc: Ohad Ben-Cohen 
cc: Linus Walleij 
cc: virtualization@lists.linux-foundation.org
cc: linux-ker...@vger.kernel.org
---

Hi Rusty,

...

>Sorry for the back and forth, I've been pondering MST's points.
>If we make a new dma-multiport device (eg. ID 11), how ugly is the code?

I don't think it's too bad.
It's a few more code lines - as I have added a new virtio_driver
definition and feature table. The rest is just replacing the check
on feature bits with driver type. I no longer need to check on
feature bits in the probe function, as the match on device type is
done automatically by the driver framework.

I actually like this new approach better.
It solves the issues Michael has pointed out, and we don't have to
think through side effects of weired combination of feature bits.

>It would be a virtio console with DMA buffers and no console, just the
>multiport stuff.  This would have no impact on the current spec for
>virtio console.

Yes, and this way it will also be easier to explain what this new
feature does.

Regards,
Sjur

 drivers/char/virtio_console.c |  133 +
 include/linux/virtio_ids.h|1 +
 2 files changed, 109 insertions(+), 25 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index cdf2f54..08593aa 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -35,6 +35,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "../tty/hvc/hvc_console.h"
 
 /*
@@ -323,6 +324,52 @@ static bool is_console_port(struct port *port)
return false;
 }
 
+#ifdef CONFIG_HAS_DMA
+static inline bool is_rproc_serial(struct virtio_device *vdev)
+{
+   return vdev->id.device == VIRTIO_ID_RPROC_SERIAL;
+}
+#else
+static inline bool is_rproc_serial(struct virtio_device *vdev)
+{
+   return false;
+}
+#endif
+
+/* Allocate data buffer from DMA memory if requested */
+static inline void *
+alloc_databuf(struct virtio_device *vdev, size_t size, gfp_t flag)
+{
+   if (is_rproc_serial(vdev)) {
+   dma_addr_t dma;
+   struct device *dev = &vdev->dev;
+   /*
+* Allocate DMA memory from ancestors. Finding the ancestor
+* is a bit quirky when DMA_MEMORY_INCLUDES_CHILDREN is not
+* implemented.
+*/
+   dev = dev->parent ? dev->parent : dev;
+   dev = dev->parent ? dev->parent : dev;
+   return dma_alloc_coherent(dev, size, &dma, flag);
+   }
+   return kzalloc(size, flag);
+}
+
+static inline void
+free_databuf(struct virtio_device *vdev, size_t size, void *cpu_addr)
+{
+
+   if (is_rproc_serial(vdev)) {
+   struct device *dev = &vdev->dev;
+   dma_addr_t dma_handle = virt_to_bus(cpu_addr);
+   dev = dev->parent ? dev->parent : dev;
+   dev = dev->parent ? dev->parent : dev;
+   dma_free_coherent(dev, size, cpu_addr, dma_handle);
+   return;
+   }
+   kfree(cpu_addr);
+}
+
 static inline bool use_multiport(struct ports_device *portdev)
 {
/*
@@ -334,20 +381,21 @@ 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 void
+free_buf(struct virtqueue *vq, struct port_buffer *buf, size_t buf_size)
 {
-   kfree(buf->buf);
+   free_databuf(vq->vdev, buf_size, buf->buf);
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)
 {
struct port_buffer *buf;
 
buf = kmalloc(sizeof(*buf), GFP_KERNEL);
if (!buf)
goto fail;
-   buf->buf = kzalloc(buf_size, GFP_KERNEL);
+   buf->buf = alloc_databuf(vq->vdev, buf_size, GFP_KERNEL);
if (!buf->buf)
goto free_buf;
buf->len = 0;
@@ -414,7 +462,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(port->in_vq, buf, PAGE_SIZE);
}
port->inbuf = NULL;
buf = get_inbuf(port);
@@ -485,7 +533,7 @@ static void reclaim_consumed_buffers(struct port *port)

[RFCv2 2/2] virtio_console: Add feature to disable console port

2012-09-06 Thread sjur . brandeland
From: Sjur Brændeland 

Add the feature VIRTIO_CONSOLE_F_NO_HVC. With this bit set
only port-devices are created. The console port and
port control virtio-queues are not created.

The console port is not suited for communicating
to a remote processor because of it's blocking behavior.
But the port-device supports efficient non-blocking IO
to a remote processor.

Signed-off-by: Sjur Brændeland 
cc: Rusty Russell 
cc: Michael S. Tsirkin 
cc: Amit Shah 
cc: Ohad Ben-Cohen 
cc: Linus Walleij 
cc: virtualization@lists.linux-foundation.org
cc: linux-ker...@vger.kernel.org
---
 drivers/char/virtio_console.c  |6 +-
 include/linux/virtio_console.h |1 +
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 469c05f..7408c00 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1244,10 +1244,13 @@ static int add_port(struct ports_device *portdev, u32 
id)
goto free_device;
}
 
+   /* Don't initialize the port_console if F_NO_HVC is set*/
+   if (virtio_has_feature(port->portdev->vdev, VIRTIO_CONSOLE_F_NO_HVC))
+   port->host_connected = true;
/*
 * If we're not using multiport support, this has to be a console port
 */
-   if (!use_multiport(port->portdev)) {
+   else if (!use_multiport(port->portdev)) {
err = init_port_console(port);
if (err)
goto free_inbufs;
@@ -1896,6 +1899,7 @@ static unsigned int features[] = {
 #if VIRTIO_CONSOLE_HAS_DMA
VIRTIO_CONSOLE_F_DMA_MEM,
 #endif
+   VIRTIO_CONSOLE_F_NO_HVC,
 
 };
 
diff --git a/include/linux/virtio_console.h b/include/linux/virtio_console.h
index b27f7fa..a7c8974 100644
--- a/include/linux/virtio_console.h
+++ b/include/linux/virtio_console.h
@@ -39,6 +39,7 @@
 #define VIRTIO_CONSOLE_F_SIZE  0   /* Does host provide console size? */
 #define VIRTIO_CONSOLE_F_MULTIPORT 1   /* Does host provide multiple ports? */
 #define VIRTIO_CONSOLE_F_DMA_MEM 2 /* Use DMA memory in vrings */
+#define VIRTIO_CONSOLE_F_NO_HVC 3  /* Disable use of HVC */
 
 #define VIRTIO_CONSOLE_BAD_ID  (~(u32)0)
 
-- 
1.7.9.5

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCHv2] virtio: Don't access device data after unregistration.

2012-09-06 Thread sjur . brandeland
From: Sjur Brændeland 

Fix panic in virtio.c when CONFIG_DEBUG_SLAB is set.
device_unregister() drops reference to device so put_device()
could invoke release callback. In this case the release
callback will free the device. Make sure we don't access
device after unregister by fetching the device index
before calling unregister.

Signed-off-by: Sjur Brændeland 
cc: Guzman Lugo, Fernadndo 
cc: Michael S. Tsirkin 
cc: Rusty Russell 
cc: Ohad Ben-Cohen 
cc: virtualization@lists.linux-foundation.org
cc: linux-ker...@vger.kernel.org
---
 drivers/virtio/virtio.c |9 -
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index c3b3f7f..faee112 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -225,8 +225,15 @@ EXPORT_SYMBOL_GPL(register_virtio_device);
 
 void unregister_virtio_device(struct virtio_device *dev)
 {
+   /*
+* device_unregister() drops reference to device so put_device could
+* invoke release callback. In case that callback will free the device,
+* make sure we don't access device after this call.
+*/
+
+   int index = dev->index;
device_unregister(&dev->dev);
-   ida_simple_remove(&virtio_index_ida, dev->index);
+   ida_simple_remove(&virtio_index_ida, index);
 }
 EXPORT_SYMBOL_GPL(unregister_virtio_device);
 
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[RFCv2 1/2] virtio_console: Add support for DMA memory allocation

2012-09-06 Thread sjur . brandeland
From: Sjur Brændeland 

Add feature VIRTIO_CONSOLE_F_DMA_MEM. If the architecture has
DMA support and this feature bit is set, the virtio data buffers
will be allocated from DMA memory. If the device requests
the feature VIRTIO_CONSOLE_F_DMA_MEM, but the architecture
don't support DMA the driver's probe function will fail.

This is needed for using virtio_console from the remoteproc
framework.

Signed-off-by: Sjur Brændeland 
cc: Rusty Russell 
cc: Michael S. Tsirkin 
cc: Amit Shah 
cc: Ohad Ben-Cohen 
cc: Linus Walleij 
cc: virtualization@lists.linux-foundation.org
cc: linux-ker...@vger.kernel.org
---
 drivers/char/virtio_console.c  |   91 +---
 include/linux/virtio_console.h |1 +
 2 files changed, 77 insertions(+), 15 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index cdf2f54..469c05f 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -35,8 +35,15 @@
 #include 
 #include 
 #include 
+#include 
 #include "../tty/hvc/hvc_console.h"
 
+#ifdef CONFIG_HAS_DMA
+#define VIRTIO_CONSOLE_HAS_DMA (1)
+#else
+#define VIRTIO_CONSOLE_HAS_DMA (0)
+#endif
+
 /*
  * This is a global struct for storing common data for all the devices
  * this driver handles.
@@ -334,20 +341,56 @@ 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)
+/* Allocate data buffer from DMA memory if requested */
+static inline void *
+alloc_databuf(struct virtio_device *vdev, size_t size, gfp_t flag)
+{
+   if (VIRTIO_CONSOLE_HAS_DMA &&
+   virtio_has_feature(vdev, VIRTIO_CONSOLE_F_DMA_MEM)) {
+   struct device *dev = &vdev->dev;
+   dma_addr_t dma;
+   /*
+* Allocate DMA memory from ancestors. Finding the ancestor
+* is a bit quirky when DMA_MEMORY_INCLUDES_CHILDREN is not
+* implemented.
+*/
+   dev = dev->parent ? dev->parent : dev;
+   dev = dev->parent ? dev->parent : dev;
+   return dma_alloc_coherent(dev, size, &dma, flag);
+   }
+   return kzalloc(size, flag);
+}
+
+static inline void
+free_databuf(struct virtio_device *vdev, size_t size, void *cpu_addr)
+{
+   if (VIRTIO_CONSOLE_HAS_DMA &&
+   virtio_has_feature(vdev, VIRTIO_CONSOLE_F_DMA_MEM)) {
+   struct device *dev = &vdev->dev;
+   dma_addr_t dma = virt_to_bus(cpu_addr);
+   dev = dev->parent ? dev->parent : dev;
+   dev = dev->parent ? dev->parent : dev;
+   dma_free_coherent(dev, size, cpu_addr, dma);
+   return;
+   }
+   kfree(cpu_addr);
+}
+
+static void
+free_buf(struct virtqueue *vq, struct port_buffer *buf, size_t buf_size)
 {
-   kfree(buf->buf);
+   free_databuf(vq->vdev, buf_size, buf);
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)
 {
struct port_buffer *buf;
 
buf = kmalloc(sizeof(*buf), GFP_KERNEL);
if (!buf)
goto fail;
-   buf->buf = kzalloc(buf_size, GFP_KERNEL);
+   buf->buf = alloc_databuf(vq->vdev, buf_size, GFP_KERNEL);
if (!buf->buf)
goto free_buf;
buf->len = 0;
@@ -414,7 +457,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(port->in_vq, buf, PAGE_SIZE);
}
port->inbuf = NULL;
buf = get_inbuf(port);
@@ -485,7 +528,7 @@ static void reclaim_consumed_buffers(struct port *port)
return;
}
while ((buf = virtqueue_get_buf(port->out_vq, &len))) {
-   kfree(buf);
+   free_databuf(port->portdev->vdev, len, buf);
port->outvq_full = false;
}
 }
@@ -672,6 +715,7 @@ static ssize_t port_fops_write(struct file *filp, const 
char __user *ubuf,
char *buf;
ssize_t ret;
bool nonblock;
+   struct virtio_device *vdev;
 
/* Userspace could be out to fool us */
if (!count)
@@ -694,9 +738,10 @@ static ssize_t port_fops_write(struct file *filp, const 
char __user *ubuf,
if (!port->guest_connected)
return -ENODEV;
 
+   vdev = port->portdev->vdev;
count = min((size_t)(32 * 1024), count);
 
-   buf = kmalloc(count, GFP_KERNEL);
+   buf = alloc_databuf(vdev, count, GFP_KERNEL);
if (!buf)
return -ENOMEM;
 
@@ -720,7 +765,8 @@ static ssize_t port_fops_write(struct file *filp, const 
char __user *ubuf,
goto out;
 
 free_buf:

[RFC 1/2] virtio_console: Add support for DMA memory allocation

2012-09-03 Thread sjur . brandeland
From: Sjur Brændeland 

Add feature VIRTIO_CONSOLE_F_DMA_MEM. If the architecture has
DMA support and this feature bit is set, the virtio data buffers
will be allocated from DMA memory.

This is needed for using virtio_console from the remoteproc
framework.

Signed-off-by: Sjur Brændeland 
cc: Rusty Russell 
cc: Michael S. Tsirkin 
cc: Ohad Ben-Cohen 
cc: Linus Walleij 
cc: virtualization@lists.linux-foundation.org
---
 drivers/char/virtio_console.c  |   76 
 include/linux/virtio_console.h |1 +
 2 files changed, 62 insertions(+), 15 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index cdf2f54..6bfbd09 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -35,6 +35,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "../tty/hvc/hvc_console.h"
 
 /*
@@ -334,20 +335,60 @@ 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)
+/* Allcoate data buffer from DMA memory if requested */
+static inline void *
+alloc_databuf(struct virtio_device *vdev, size_t size, dma_addr_t *dma_handle,
+  gfp_t flag)
 {
-   kfree(buf->buf);
+#ifdef CONFIG_HAS_DMA
+   if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_DMA_MEM)) {
+   struct device *dev = &vdev->dev;
+   /*
+* Allocate DMA memory from ancestors. Finding the ancestor
+* is a bit quirky when DMA_MEMORY_INCLUDES_CHILDREN is not
+* implemented.
+*/
+   dev = dev->parent ? dev->parent : dev;
+   dev = dev->parent ? dev->parent : dev;
+   return dma_alloc_coherent(dev, size, dma_handle, flag);
+   }
+#endif
+   return kzalloc(size, flag);
+}
+
+static inline void
+free_databuf(struct virtio_device *vdev, size_t size, void *cpu_addr)
+{
+#ifdef CONFIG_HAS_DMA
+   dma_addr_t dma_handle = virt_to_bus(cpu_addr);
+   if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_DMA_MEM)) {
+   struct device *dev = &vdev->dev;
+
+   dev = dev->parent ? dev->parent : dev;
+   dev = dev->parent ? dev->parent : dev;
+   dma_free_coherent(dev, size, cpu_addr, dma_handle);
+   return;
+   }
+#endif
+   kfree(cpu_addr);
+}
+
+static void
+free_buf(struct virtqueue *vq, struct port_buffer *buf, size_t buf_size)
+{
+   free_databuf(vq->vdev, buf_size, buf);
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)
 {
struct port_buffer *buf;
+   dma_addr_t dma;
 
buf = kmalloc(sizeof(*buf), GFP_KERNEL);
if (!buf)
goto fail;
-   buf->buf = kzalloc(buf_size, GFP_KERNEL);
+   buf->buf = alloc_databuf(vq->vdev, buf_size, &dma, GFP_KERNEL);
if (!buf->buf)
goto free_buf;
buf->len = 0;
@@ -414,7 +455,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(port->in_vq, buf, PAGE_SIZE);
}
port->inbuf = NULL;
buf = get_inbuf(port);
@@ -485,7 +526,7 @@ static void reclaim_consumed_buffers(struct port *port)
return;
}
while ((buf = virtqueue_get_buf(port->out_vq, &len))) {
-   kfree(buf);
+   free_databuf(port->portdev->vdev, len, buf);
port->outvq_full = false;
}
 }
@@ -672,6 +713,8 @@ static ssize_t port_fops_write(struct file *filp, const 
char __user *ubuf,
char *buf;
ssize_t ret;
bool nonblock;
+   struct virtio_device *vdev;
+   dma_addr_t dma;
 
/* Userspace could be out to fool us */
if (!count)
@@ -694,9 +737,10 @@ static ssize_t port_fops_write(struct file *filp, const 
char __user *ubuf,
if (!port->guest_connected)
return -ENODEV;
 
+   vdev = port->portdev->vdev;
count = min((size_t)(32 * 1024), count);
 
-   buf = kmalloc(count, GFP_KERNEL);
+   buf = alloc_databuf(vdev, count, &dma, GFP_KERNEL);
if (!buf)
return -ENOMEM;
 
@@ -720,7 +764,8 @@ static ssize_t port_fops_write(struct file *filp, const 
char __user *ubuf,
goto out;
 
 free_buf:
-   kfree(buf);
+   free_databuf(vdev, count, buf);
+
 out:
return ret;
 }
@@ -1102,7 +1147,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);
  

[RFC 2/2] virtio_console: Add feature to disable console port

2012-09-03 Thread sjur . brandeland
From: Sjur Brændeland 

Add the feature VIRTIO_CONSOLE_F_NO_HVC. With this bit set
only port-devices are created. The console port and
port control virtio-queues are not created.

The console port is not suited for communicating
to a remote processor because of it's blocking behavior.
But the port-device supports efficient non-blocking IO
to a remote processor.

Signed-off-by: Sjur Brændeland 
cc: Rusty Russell 
cc: Michael S. Tsirkin 
cc: virtualization@lists.linux-foundation.org
cc: Ohad Ben-Cohen 
cc: Linus Walleij 
---
 drivers/char/virtio_console.c  |5 -
 include/linux/virtio_console.h |1 +
 2 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 6bfbd09..81546e9 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1246,7 +1246,9 @@ static int add_port(struct ports_device *portdev, u32 id)
/*
 * If we're not using multiport support, this has to be a console port
 */
-   if (!use_multiport(port->portdev)) {
+   if (virtio_has_feature(port->portdev->vdev, VIRTIO_CONSOLE_F_NO_HVC))
+   port->host_connected = true;
+   else if (!use_multiport(port->portdev)) {
err = init_port_console(port);
if (err)
goto free_inbufs;
@@ -1882,6 +1884,7 @@ static unsigned int features[] = {
VIRTIO_CONSOLE_F_SIZE,
VIRTIO_CONSOLE_F_MULTIPORT,
VIRTIO_CONSOLE_F_DMA_MEM,
+   VIRTIO_CONSOLE_F_NO_HVC,
 };
 
 #ifdef CONFIG_PM
diff --git a/include/linux/virtio_console.h b/include/linux/virtio_console.h
index b27f7fa..a7c8974 100644
--- a/include/linux/virtio_console.h
+++ b/include/linux/virtio_console.h
@@ -39,6 +39,7 @@
 #define VIRTIO_CONSOLE_F_SIZE  0   /* Does host provide console size? */
 #define VIRTIO_CONSOLE_F_MULTIPORT 1   /* Does host provide multiple ports? */
 #define VIRTIO_CONSOLE_F_DMA_MEM 2 /* Use DMA memory in vrings */
+#define VIRTIO_CONSOLE_F_NO_HVC 3  /* Disable use of HVC */
 
 #define VIRTIO_CONSOLE_BAD_ID  (~(u32)0)
 
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

[PATCH] virtio: Don't access device data after unregistration.

2012-09-03 Thread sjur . brandeland
From: Sjur Brændeland 

Fix panic in virtio.c when CONFIG_DEBUG_SLAB is set.
Use device_del() and put_device() instead of
device_unregister(), and access device data before
calling put_device().


Signed-off-by: Sjur Brændeland 
cc: Guzman Lugo, Fernadndo 
cc: Michael S. Tsirkin 
cc: virtualization@lists.linux-foundation.org
cc: Ohad Ben-Cohen 
---
 drivers/virtio/virtio.c |3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index c3b3f7f..71eacd1 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -225,8 +225,9 @@ EXPORT_SYMBOL_GPL(register_virtio_device);
 
 void unregister_virtio_device(struct virtio_device *dev)
 {
-   device_unregister(&dev->dev);
+   device_del(&dev->dev);
ida_simple_remove(&virtio_index_ida, dev->index);
+   put_device(&dev->dev);
 }
 EXPORT_SYMBOL_GPL(unregister_virtio_device);
 
-- 
1.7.5.4

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization