[PATCH net-next v2 0/3] Multiqueue support in virtio-net

2012-12-05 Thread Jason Wang
Hi all:

This series is an update version of multiqueue virtio-net driver based on
Krishna Kumar's work to let virtio-net use multiple rx/tx queues to do the
packets reception and transmission. Please review and comments.

A protype implementation of qemu-kvm support could by found in
git://github.com/jasowang/qemu-kvm-mq.git. To start a guest with two queues, you
could specify the queues parameters to both tap and virtio-net like:

./qemu-kvm -netdev tap,queues=2,... -device virtio-net-pci,queues=2,...

then enable the multiqueue through ethtool by:

ethtool -L eth0 combined 2

Changes from V1:
Addressing Michael's comments:
- fix typos in commit log
- don't move virtnet_open()
- don't set to NULL in virtnet_free_queues()
- style  comment fixes
- conditionally set the irq affinity hint based on online cpus and queue pairs
- move the virnet_del_vqs to patch 1
- change the meaningless kzalloc() to kmalloc()
- open code the err handling
- store the name of virtqueue in send/receive queue
- avoid type cast in virtnet_find_vqs()
- fix the mem leak and freeing issue of names in virtnet_find_vqs()
- check cvq during before setting the max_queue_pairs in virtnet_probe()
- check the cvq and VIRTIO_NET_F_RFS in virtnet_set_queues()
- set the curr_queue_pairs in virtnet_set_queue()
- use the err report by virtnet_set_queue() as the return value of
  ethtool_set_channels()

Changes from RFC v7:
Addressing Rusty's comments:
- align the implementation (location of cvq) to v5.
- fix the style issue.
- use a global refill instead of per-vq one.
- check the VIRTIO_NET_F_RFS before calling virtnet_set_queues()

Addresing Michael's comments
- rename the curr_queue_pairs in virtnet_probe() to max_queue_pairs
- validate the number of queue pairs supported by the device against
  VIRTIO_NET_CTRL_RFS_VQ_PAIRS_MIN and VIRTIO_NET_CTRL_RFS_VQ_PAIRS_MAX.
- don't crash when failing to change the number of virtqueues
- don't set the affinity hint when onle single queue is used or there's too much
  virtqueues
- add a TODO of handling cpu hotplug
- allow user to set the nubmer of queue pairs between 1 and max_queue_pairs

Changes from RFC v6:
- Align the implementation with the RFC spec update v5
- Addressing Rusty's comments:
  * split the patches
  * rename to max_queue_pairs and curr_queue_pairs
  * remove the useless status
  * fix the hibernation bug
- Addressing Ben's comments:
  * check other parameters in ethtool_set_queues

Changes from RFC v5:
- Align the implementation with the RFC spec update v4
- Switch the mode between single mode and multiqueue mode without reset
- Remove the 256 limitation of queues
- Use helpers to do the mapping between virtqueues and tx/rx queues
- Use commbined channels instead of separated rx/tx queus when do the queue
  number configuartion
- Other coding style comments from Michael

Changes from RFC v4:
- Add ability to negotiate the number of queues through control virtqueue
- Ethtool -{L|l} support and default the tx/rx queue number to 1
- Expose the API to set irq affinity instead of irq itself

Changes from RFC v3:
- Rebase to the net-next
- Let queue 2 to be the control virtqueue to obey the spec
- Prodives irq affinity
- Choose txq based on processor id

Reference:
- Virtio spec RFC: http://patchwork.ozlabs.org/patch/201303/
- V1: https://lkml.org/lkml/2012/11/27/177
- RFC V7: https://lkml.org/lkml/2012/11/27/177a
- RFC V6: https://lkml.org/lkml/2012/10/30/127
- RFC V5: http://lwn.net/Articles/505388/
- RFC V4: https://lkml.org/lkml/2012/6/25/120
- RFC V2: http://lwn.net/Articles/467283/

Perf Numbers:

Will do some basic test and post as a reply to this mail.

Jason Wang (3):
  virtio-net: separate fields of sending/receiving queue from
virtnet_info
  virtio_net: multiqueue support
  virtio-net: support changing the number of queue pairs through
ethtool

 drivers/net/virtio_net.c|  726 +--
 include/uapi/linux/virtio_net.h |   27 ++
 2 files changed, 567 insertions(+), 186 deletions(-)

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


[PATCH net-next v2 1/3] virtio-net: separate fields of sending/receiving queue from virtnet_info

2012-12-05 Thread Jason Wang
To support multiqueue transmitq/receiveq, the first step is to separate queue
related structure from virtnet_info. This patch introduce send_queue and
receive_queue structure and use the pointer to them as the parameter in
functions handling sending/receiving.

Signed-off-by: Krishna Kumar krkum...@in.ibm.com
Signed-off-by: Jason Wang jasow...@redhat.com
---
 drivers/net/virtio_net.c |  282 ++
 1 files changed, 158 insertions(+), 124 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 8262232..0dcaee7 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -51,16 +51,40 @@ struct virtnet_stats {
u64 rx_packets;
 };
 
-struct virtnet_info {
-   struct virtio_device *vdev;
-   struct virtqueue *rvq, *svq, *cvq;
-   struct net_device *dev;
+/* Internal representation of a send virtqueue */
+struct send_queue {
+   /* Virtqueue associated with this send _queue */
+   struct virtqueue *vq;
+
+   /* TX: fragments + linear part + virtio header */
+   struct scatterlist sg[MAX_SKB_FRAGS + 2];
+};
+
+/* Internal representation of a receive virtqueue */
+struct receive_queue {
+   /* Virtqueue associated with this receive_queue */
+   struct virtqueue *vq;
+
struct napi_struct napi;
-   unsigned int status;
 
/* Number of input buffers, and max we've ever had. */
unsigned int num, max;
 
+   /* Chain pages by the private ptr. */
+   struct page *pages;
+
+   /* RX: fragments + linear part + virtio header */
+   struct scatterlist sg[MAX_SKB_FRAGS + 2];
+};
+
+struct virtnet_info {
+   struct virtio_device *vdev;
+   struct virtqueue *cvq;
+   struct net_device *dev;
+   struct send_queue sq;
+   struct receive_queue rq;
+   unsigned int status;
+
/* I like... big packets and I cannot lie! */
bool big_packets;
 
@@ -81,13 +105,6 @@ struct virtnet_info {
 
/* Lock for config space updates */
struct mutex config_lock;
-
-   /* Chain pages by the private ptr. */
-   struct page *pages;
-
-   /* fragments + linear part + virtio header */
-   struct scatterlist rx_sg[MAX_SKB_FRAGS + 2];
-   struct scatterlist tx_sg[MAX_SKB_FRAGS + 2];
 };
 
 struct skb_vnet_hdr {
@@ -117,22 +134,22 @@ static inline struct skb_vnet_hdr *skb_vnet_hdr(struct 
sk_buff *skb)
  * private is used to chain pages for big packets, put the whole
  * most recent used list in the beginning for reuse
  */
-static void give_pages(struct virtnet_info *vi, struct page *page)
+static void give_pages(struct receive_queue *rq, struct page *page)
 {
struct page *end;
 
-   /* Find end of list, sew whole thing into vi-pages. */
+   /* Find end of list, sew whole thing into vi-rq.pages. */
for (end = page; end-private; end = (struct page *)end-private);
-   end-private = (unsigned long)vi-pages;
-   vi-pages = page;
+   end-private = (unsigned long)rq-pages;
+   rq-pages = page;
 }
 
-static struct page *get_a_page(struct virtnet_info *vi, gfp_t gfp_mask)
+static struct page *get_a_page(struct receive_queue *rq, gfp_t gfp_mask)
 {
-   struct page *p = vi-pages;
+   struct page *p = rq-pages;
 
if (p) {
-   vi-pages = (struct page *)p-private;
+   rq-pages = (struct page *)p-private;
/* clear private here, it is used to chain pages */
p-private = 0;
} else
@@ -140,12 +157,12 @@ static struct page *get_a_page(struct virtnet_info *vi, 
gfp_t gfp_mask)
return p;
 }
 
-static void skb_xmit_done(struct virtqueue *svq)
+static void skb_xmit_done(struct virtqueue *vq)
 {
-   struct virtnet_info *vi = svq-vdev-priv;
+   struct virtnet_info *vi = vq-vdev-priv;
 
/* Suppress further interrupts. */
-   virtqueue_disable_cb(svq);
+   virtqueue_disable_cb(vq);
 
/* We were probably waiting for more output buffers. */
netif_wake_queue(vi-dev);
@@ -167,9 +184,10 @@ static void set_skb_frag(struct sk_buff *skb, struct page 
*page,
 }
 
 /* Called from bottom half context */
-static struct sk_buff *page_to_skb(struct virtnet_info *vi,
+static struct sk_buff *page_to_skb(struct receive_queue *rq,
   struct page *page, unsigned int len)
 {
+   struct virtnet_info *vi = rq-vq-vdev-priv;
struct sk_buff *skb;
struct skb_vnet_hdr *hdr;
unsigned int copy, hdr_len, offset;
@@ -224,12 +242,12 @@ static struct sk_buff *page_to_skb(struct virtnet_info 
*vi,
}
 
if (page)
-   give_pages(vi, page);
+   give_pages(rq, page);
 
return skb;
 }
 
-static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb)
+static int receive_mergeable(struct receive_queue *rq, struct sk_buff *skb)
 {
struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb);
struct page 

[PATCH net-next v2 2/3] virtio_net: multiqueue support

2012-12-05 Thread Jason Wang
This patch adds the multiqueue (VIRTIO_NET_F_RFS) support to virtio_net
driver. VIRTIO_NET_F_RFS capable device could allow the driver to do packet
transmission and reception through multiple queue pairs and does the packet
steering to get better performance. By default, one one queue pair is used, user
could change the number of queue pairs by ethtool in the next patch.

When multiple queue pairs is used and the number of queue pairs is equal to the
number of vcpus. Driver does the following optimizations to implement per-cpu
virt queue pairs:

- select the txq based on the smp processor id.
- smp affinity hint to the cpu that owns the queue pairs.

This could be used with the flow steering support of the device to guarantee the
packets of a single flow is handled by the same cpu.

Signed-off-by: Krishna Kumar krkum...@in.ibm.com
Signed-off-by: Jason Wang jasow...@redhat.com
---
 drivers/net/virtio_net.c|  473 +++
 include/uapi/linux/virtio_net.h |   27 +++
 2 files changed, 402 insertions(+), 98 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 0dcaee7..def11ce 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -58,6 +58,9 @@ struct send_queue {
 
/* TX: fragments + linear part + virtio header */
struct scatterlist sg[MAX_SKB_FRAGS + 2];
+
+   /* Name of the send queue: output.$index */
+   char name[40];
 };
 
 /* Internal representation of a receive virtqueue */
@@ -75,22 +78,34 @@ struct receive_queue {
 
/* RX: fragments + linear part + virtio header */
struct scatterlist sg[MAX_SKB_FRAGS + 2];
+
+   /* Name of this receive queue: input.$index */
+   char name[40];
 };
 
 struct virtnet_info {
struct virtio_device *vdev;
struct virtqueue *cvq;
struct net_device *dev;
-   struct send_queue sq;
-   struct receive_queue rq;
+   struct send_queue *sq;
+   struct receive_queue *rq;
unsigned int status;
 
+   /* Max # of queue pairs supported by the device */
+   u16 max_queue_pairs;
+
+   /* # of queue pairs currently used by the driver */
+   u16 curr_queue_pairs;
+
/* I like... big packets and I cannot lie! */
bool big_packets;
 
/* Host will merge rx buffers for big packets (shake it! shake it!) */
bool mergeable_rx_bufs;
 
+   /* Has control virtqueue */
+   bool has_cvq;
+
/* enable config space updates */
bool config_enable;
 
@@ -105,6 +120,9 @@ struct virtnet_info {
 
/* Lock for config space updates */
struct mutex config_lock;
+
+   /* Does the affinity hint is set for virtqueues? */
+   bool affinity_hint_set;
 };
 
 struct skb_vnet_hdr {
@@ -125,6 +143,29 @@ struct padded_vnet_hdr {
char padding[6];
 };
 
+/* Converting between virtqueue no. and kernel tx/rx queue no.
+ * 0:rx0 1:tx0 2:rx1 3:tx1 ... 2N:rxN 2N+1:txN 2N+2:cvq
+ */
+static int vq2txq(struct virtqueue *vq)
+{
+   return (virtqueue_get_queue_index(vq) - 1) / 2;
+}
+
+static int txq2vq(int txq)
+{
+   return txq * 2 + 1;
+}
+
+static int vq2rxq(struct virtqueue *vq)
+{
+   return virtqueue_get_queue_index(vq) / 2;
+}
+
+static int rxq2vq(int rxq)
+{
+   return rxq * 2;
+}
+
 static inline struct skb_vnet_hdr *skb_vnet_hdr(struct sk_buff *skb)
 {
return (struct skb_vnet_hdr *)skb-cb;
@@ -165,7 +206,7 @@ static void skb_xmit_done(struct virtqueue *vq)
virtqueue_disable_cb(vq);
 
/* We were probably waiting for more output buffers. */
-   netif_wake_queue(vi-dev);
+   netif_wake_subqueue(vi-dev, vq2txq(vq));
 }
 
 static void set_skb_frag(struct sk_buff *skb, struct page *page,
@@ -502,7 +543,7 @@ static bool try_fill_recv(struct receive_queue *rq, gfp_t 
gfp)
 static void skb_recv_done(struct virtqueue *rvq)
 {
struct virtnet_info *vi = rvq-vdev-priv;
-   struct receive_queue *rq = vi-rq;
+   struct receive_queue *rq = vi-rq[vq2rxq(rvq)];
 
/* Schedule NAPI, Suppress further interrupts if successful. */
if (napi_schedule_prep(rq-napi)) {
@@ -532,15 +573,21 @@ static void refill_work(struct work_struct *work)
struct virtnet_info *vi =
container_of(work, struct virtnet_info, refill.work);
bool still_empty;
+   int i;
+
+   for (i = 0; i  vi-max_queue_pairs; i++) {
+   struct receive_queue *rq = vi-rq[i];
 
-   napi_disable(vi-rq.napi);
-   still_empty = !try_fill_recv(vi-rq, GFP_KERNEL);
-   virtnet_napi_enable(vi-rq);
+   napi_disable(rq-napi);
+   still_empty = !try_fill_recv(rq, GFP_KERNEL);
+   virtnet_napi_enable(rq);
 
-   /* In theory, this can happen: if we don't get any buffers in
-* we will *never* try to fill again. */
-   if (still_empty)
-   schedule_delayed_work(vi-refill, HZ/2);
+   /* In theory, this can 

[PATCH net-next v2 3/3] virtio-net: support changing the number of queue pairs through ethtool

2012-12-05 Thread Jason Wang
This patch implements the ethtool_{set|get}_channels method of virtio-net to
allow user to change the number of queues when the device is running on demand.

Signed-off-by: Jason Wang jasow...@redhat.com
---
 drivers/net/virtio_net.c |   43 +++
 1 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index def11ce..51c9b75 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -1075,10 +1075,53 @@ static void virtnet_get_drvinfo(struct net_device *dev,
 
 }
 
+/* TODO: Eliminate OOO packets during switching */
+static int virtnet_set_channels(struct net_device *dev,
+   struct ethtool_channels *channels)
+{
+   struct virtnet_info *vi = netdev_priv(dev);
+   u16 queue_pairs = channels-combined_count;
+   int err;
+
+   /* We don't support separate rx/tx channels.
+* We don't allow setting 'other' channels.
+*/
+   if (channels-rx_count || channels-tx_count || channels-other_count)
+   return -EINVAL;
+
+   if (queue_pairs  vi-max_queue_pairs)
+   return -EINVAL;
+
+   err = virtnet_set_queues(vi, queue_pairs);
+   if (!err) {
+   netif_set_real_num_tx_queues(dev, queue_pairs);
+   netif_set_real_num_rx_queues(dev, queue_pairs);
+
+   virtnet_set_affinity(vi, true);
+   }
+
+   return err;
+}
+
+static void virtnet_get_channels(struct net_device *dev,
+struct ethtool_channels *channels)
+{
+   struct virtnet_info *vi = netdev_priv(dev);
+
+   channels-combined_count = vi-curr_queue_pairs;
+   channels-max_combined = vi-max_queue_pairs;
+   channels-max_other = 0;
+   channels-rx_count = 0;
+   channels-tx_count = 0;
+   channels-other_count = 0;
+}
+
 static const struct ethtool_ops virtnet_ethtool_ops = {
.get_drvinfo = virtnet_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_ringparam = virtnet_get_ringparam,
+   .set_channels = virtnet_set_channels,
+   .get_channels = virtnet_get_channels,
 };
 
 #define MIN_MTU 68
-- 
1.7.1

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


Re: [PATCH 2/3] virtio: use dev_to_virtio wrapper in virtio

2012-12-05 Thread Michael S. Tsirkin
On Wed, Dec 05, 2012 at 03:03:28PM +0800, Wanlong Gao wrote:
 Use dev_to_virtio wrapper in virtio to make code clearly.
 
 Signed-off-by: Wanlong Gao gaowanl...@cn.fujitsu.com
 ---
 diff --git a/include/linux/virtio.h b/include/linux/virtio.h
 index 25fa1a6..30fc3c9 100644
 --- a/include/linux/virtio.h
 +++ b/include/linux/virtio.h
 @@ -79,7 +79,7 @@ struct virtio_device {
   void *priv;
  };
  
 -#define dev_to_virtio(dev) container_of(dev, struct virtio_device, dev)
 +#define dev_to_virtio(_dev) container_of(_dev, struct virtio_device, dev)
  int register_virtio_device(struct virtio_device *dev);
  void unregister_virtio_device(struct virtio_device *dev);


More importantly this would fix dev_to_virtio since ATM

dev_to_virtio(_d) resolves to
 container_of(_d, struct virtio_device, _d)

which is not what was intended.

However, I think this shows that using a macro here
is a mistake. Could you code this up with a static inline
function instead please?

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


Re: [PATCH 2/3] virtio: use dev_to_virtio wrapper in virtio

2012-12-05 Thread Michael S. Tsirkin
On Wed, Dec 05, 2012 at 01:16:06PM +0200, Michael S. Tsirkin wrote:
 On Wed, Dec 05, 2012 at 03:03:28PM +0800, Wanlong Gao wrote:
  Use dev_to_virtio wrapper in virtio to make code clearly.
  
  Signed-off-by: Wanlong Gao gaowanl...@cn.fujitsu.com
  ---
  diff --git a/include/linux/virtio.h b/include/linux/virtio.h
  index 25fa1a6..30fc3c9 100644
  --- a/include/linux/virtio.h
  +++ b/include/linux/virtio.h
  @@ -79,7 +79,7 @@ struct virtio_device {
  void *priv;
   };
   
  -#define dev_to_virtio(dev) container_of(dev, struct virtio_device, dev)
  +#define dev_to_virtio(_dev) container_of(_dev, struct virtio_device, dev)
   int register_virtio_device(struct virtio_device *dev);
   void unregister_virtio_device(struct virtio_device *dev);
 
 
 More importantly this would fix dev_to_virtio since ATM
 
 dev_to_virtio(_d) resolves to
  container_of(_d, struct virtio_device, _d)
 
 which is not what was intended.
 
 However, I think this shows that using a macro here
 is a mistake. Could you code this up with a static inline
 function instead please?

And probably move it to virtio.c there seems to be no need
to keep it in virtio.h

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


Re: [PATCH 3/3] virtio: add drv_to_virtio to make code clearly

2012-12-05 Thread Michael S. Tsirkin
On Wed, Dec 05, 2012 at 03:03:29PM +0800, Wanlong Gao wrote:
 Add drv_to_virtio wrapper to get virtio_driver from device_driver.
 
 Signed-off-by: Wanlong Gao gaowanl...@cn.fujitsu.com

IMHO a function would be slightly better.

 ---
  drivers/virtio/virtio.c | 11 ---
  include/linux/virtio.h  |  1 +
  2 files changed, 5 insertions(+), 7 deletions(-)
 
 diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
 index 1346ae8..1c01ac3 100644
 --- a/drivers/virtio/virtio.c
 +++ b/drivers/virtio/virtio.c
 @@ -73,7 +73,7 @@ static int virtio_dev_match(struct device *_dv, struct 
 device_driver *_dr)
   struct virtio_device *dev = dev_to_virtio(_dv);
   const struct virtio_device_id *ids;
  
 - ids = container_of(_dr, struct virtio_driver, driver)-id_table;
 + ids = drv_to_virtio(_dr)-id_table;
   for (i = 0; ids[i].device; i++)
   if (virtio_id_match(dev, ids[i]))
   return 1;
 @@ -97,8 +97,7 @@ void virtio_check_driver_offered_feature(const struct 
 virtio_device *vdev,
unsigned int fbit)
  {
   unsigned int i;
 - struct virtio_driver *drv = container_of(vdev-dev.driver,
 -  struct virtio_driver, driver);
 + struct virtio_driver *drv = drv_to_virtio(vdev-dev.driver);
  
   for (i = 0; i  drv-feature_table_size; i++)
   if (drv-feature_table[i] == fbit)
 @@ -111,8 +110,7 @@ static int virtio_dev_probe(struct device *_d)
  {
   int err, i;
   struct virtio_device *dev = dev_to_virtio(_d);
 - struct virtio_driver *drv = container_of(dev-dev.driver,
 -  struct virtio_driver, driver);
 + struct virtio_driver *drv = drv_to_virtio(dev-dev.driver);
   u32 device_features;
  
   /* We have a driver! */
 @@ -152,8 +150,7 @@ static int virtio_dev_probe(struct device *_d)
  static int virtio_dev_remove(struct device *_d)
  {
   struct virtio_device *dev = dev_to_virtio(_d);
 - struct virtio_driver *drv = container_of(dev-dev.driver,
 -  struct virtio_driver, driver);
 + struct virtio_driver *drv = drv_to_virtio(dev-dev.driver);
  
   drv-remove(dev);
  
 diff --git a/include/linux/virtio.h b/include/linux/virtio.h
 index 30fc3c9..8da5811 100644
 --- a/include/linux/virtio.h
 +++ b/include/linux/virtio.h
 @@ -109,6 +109,7 @@ struct virtio_driver {
  #endif
  };
  
 +#define drv_to_virtio(drv) container_of(drv, struct virtio_driver, driver)
  int register_virtio_driver(struct virtio_driver *drv);
  void unregister_virtio_driver(struct virtio_driver *drv);
  #endif /* _LINUX_VIRTIO_H */
 -- 
 1.8.0
___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization


Re: [PATCH 1/3] virtio: change to_vp_device to an inlined definition

2012-12-05 Thread Michael S. Tsirkin
On Wed, Dec 05, 2012 at 03:03:27PM +0800, Wanlong Gao wrote:
 to_vp_device is worth changing to inlined definition.
 
 Signed-off-by: Wanlong Gao gaowanl...@cn.fujitsu.com

I don't think it's worth it.
The oldest gcc I happened to have around is 4.3.3
which is already smart enough to generate
identical code before and after the patch.

And a function is cleaner.

 ---
  drivers/virtio/virtio_pci.c | 6 +-
  1 file changed, 1 insertion(+), 5 deletions(-)
 
 diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
 index e3ecc94..7681fe3 100644
 --- a/drivers/virtio/virtio_pci.c
 +++ b/drivers/virtio/virtio_pci.c
 @@ -98,11 +98,7 @@ static struct pci_device_id virtio_pci_id_table[] = {
  
  MODULE_DEVICE_TABLE(pci, virtio_pci_id_table);
  
 -/* Convert a generic virtio device to our structure */
 -static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev)
 -{
 - return container_of(vdev, struct virtio_pci_device, vdev);
 -}
 +#define to_vp_device(_vdev) container_of(_vdev, struct virtio_pci_device, 
 vdev)
  
  /* virtio config-get_features() implementation */
  static u32 vp_get_features(struct virtio_device *vdev)
 -- 
 1.8.0
___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization


[PATCH V2 2/2] virtio: add drv_to_virtio to make code clearly

2012-12-05 Thread Wanlong Gao
Add drv_to_virtio wrapper to get virtio_driver from device_driver.

Signed-off-by: Wanlong Gao gaowanl...@cn.fujitsu.com
---
 drivers/virtio/virtio.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index ba24e87..43c1fb2 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -11,6 +11,10 @@ static inline struct virtio_device *dev_to_virtio(struct 
device *_dev)
 {
return container_of(_dev, struct virtio_device, dev);
 }
+static inline struct virtio_driver *drv_to_virtio(struct device_driver *drv)
+{
+   return container_of(drv, struct virtio_driver, driver);
+}
 
 static ssize_t device_show(struct device *_d,
   struct device_attribute *attr, char *buf)
@@ -78,7 +82,7 @@ static int virtio_dev_match(struct device *_dv, struct 
device_driver *_dr)
struct virtio_device *dev = dev_to_virtio(_dv);
const struct virtio_device_id *ids;
 
-   ids = container_of(_dr, struct virtio_driver, driver)-id_table;
+   ids = drv_to_virtio(_dr)-id_table;
for (i = 0; ids[i].device; i++)
if (virtio_id_match(dev, ids[i]))
return 1;
@@ -102,8 +106,7 @@ void virtio_check_driver_offered_feature(const struct 
virtio_device *vdev,
 unsigned int fbit)
 {
unsigned int i;
-   struct virtio_driver *drv = container_of(vdev-dev.driver,
-struct virtio_driver, driver);
+   struct virtio_driver *drv = drv_to_virtio(vdev-dev.driver);
 
for (i = 0; i  drv-feature_table_size; i++)
if (drv-feature_table[i] == fbit)
@@ -116,8 +119,7 @@ static int virtio_dev_probe(struct device *_d)
 {
int err, i;
struct virtio_device *dev = dev_to_virtio(_d);
-   struct virtio_driver *drv = container_of(dev-dev.driver,
-struct virtio_driver, driver);
+   struct virtio_driver *drv = drv_to_virtio(dev-dev.driver);
u32 device_features;
 
/* We have a driver! */
@@ -157,8 +159,7 @@ static int virtio_dev_probe(struct device *_d)
 static int virtio_dev_remove(struct device *_d)
 {
struct virtio_device *dev = dev_to_virtio(_d);
-   struct virtio_driver *drv = container_of(dev-dev.driver,
-struct virtio_driver, driver);
+   struct virtio_driver *drv = drv_to_virtio(dev-dev.driver);
 
drv-remove(dev);
 
-- 
1.8.0

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


[PATCH V2 1/2] virtio: use dev_to_virtio wrapper in virtio

2012-12-05 Thread Wanlong Gao
Use dev_to_virtio wrapper in virtio to make code clearly.
Move dev_to_virtio from virtio.h to virtio.c.

Signed-off-by: Wanlong Gao gaowanl...@cn.fujitsu.com
---
 drivers/virtio/virtio.c | 24 ++--
 include/linux/virtio.h  |  1 -
 2 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index 1e8659c..ba24e87 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -7,36 +7,40 @@
 /* Unique numbering for virtio devices. */
 static DEFINE_IDA(virtio_index_ida);
 
+static inline struct virtio_device *dev_to_virtio(struct device *_dev)
+{
+   return container_of(_dev, struct virtio_device, dev);
+}
+
 static ssize_t device_show(struct device *_d,
   struct device_attribute *attr, char *buf)
 {
-   struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
+   struct virtio_device *dev = dev_to_virtio(_d);
return sprintf(buf, 0x%04x\n, dev-id.device);
 }
 static ssize_t vendor_show(struct device *_d,
   struct device_attribute *attr, char *buf)
 {
-   struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
+   struct virtio_device *dev = dev_to_virtio(_d);
return sprintf(buf, 0x%04x\n, dev-id.vendor);
 }
 static ssize_t status_show(struct device *_d,
   struct device_attribute *attr, char *buf)
 {
-   struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
+   struct virtio_device *dev = dev_to_virtio(_d);
return sprintf(buf, 0x%08x\n, dev-config-get_status(dev));
 }
 static ssize_t modalias_show(struct device *_d,
 struct device_attribute *attr, char *buf)
 {
-   struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
-
+   struct virtio_device *dev = dev_to_virtio(_d);
return sprintf(buf, virtio:d%08Xv%08X\n,
   dev-id.device, dev-id.vendor);
 }
 static ssize_t features_show(struct device *_d,
 struct device_attribute *attr, char *buf)
 {
-   struct virtio_device *dev = container_of(_d, struct virtio_device, dev);
+   struct virtio_device *dev = dev_to_virtio(_d);
unsigned int i;
ssize_t len = 0;
 
@@ -71,7 +75,7 @@ static inline int virtio_id_match(const struct virtio_device 
*dev,
 static int virtio_dev_match(struct device *_dv, struct device_driver *_dr)
 {
unsigned int i;
-   struct virtio_device *dev = container_of(_dv,struct virtio_device,dev);
+   struct virtio_device *dev = dev_to_virtio(_dv);
const struct virtio_device_id *ids;
 
ids = container_of(_dr, struct virtio_driver, driver)-id_table;
@@ -83,7 +87,7 @@ static int virtio_dev_match(struct device *_dv, struct 
device_driver *_dr)
 
 static int virtio_uevent(struct device *_dv, struct kobj_uevent_env *env)
 {
-   struct virtio_device *dev = container_of(_dv,struct virtio_device,dev);
+   struct virtio_device *dev = dev_to_virtio(_dv);
 
return add_uevent_var(env, MODALIAS=virtio:d%08Xv%08X,
  dev-id.device, dev-id.vendor);
@@ -111,7 +115,7 @@ EXPORT_SYMBOL_GPL(virtio_check_driver_offered_feature);
 static int virtio_dev_probe(struct device *_d)
 {
int err, i;
-   struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
+   struct virtio_device *dev = dev_to_virtio(_d);
struct virtio_driver *drv = container_of(dev-dev.driver,
 struct virtio_driver, driver);
u32 device_features;
@@ -152,7 +156,7 @@ static int virtio_dev_probe(struct device *_d)
 
 static int virtio_dev_remove(struct device *_d)
 {
-   struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
+   struct virtio_device *dev = dev_to_virtio(_d);
struct virtio_driver *drv = container_of(dev-dev.driver,
 struct virtio_driver, driver);
 
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index 25fa1a6..4a8768f 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -79,7 +79,6 @@ struct virtio_device {
void *priv;
 };
 
-#define dev_to_virtio(dev) container_of(dev, struct virtio_device, dev)
 int register_virtio_device(struct virtio_device *dev);
 void unregister_virtio_device(struct virtio_device *dev);
 
-- 
1.8.0

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


[RFCv2 00/12] Introduce host-side virtio queue and CAIF Virtio.

2012-12-05 Thread Sjur Brændeland
From: Sjur Brændeland sjur.brandel...@stericsson.com

This patch-set introduces a host-side virtqueue implementation and
the CAIF Virtio Link layer. See http://lwn.net/Articles/522296/ for
background info on CAIF over Virtio.

After feedback from Rusty, I have re-factored vhost.c and
pulled out common functionality and data definitions from
drivers/vhost into drivers/virtio.

Part of the challenge of doing this is that vhost.c is accessing the
virtio rings from user-space, while CAIF uses kernel memory.
In order to solve this issue, inline memory access functions are passed
to some of the vring functions (as suggested by Rusty).

I have added one argument to the function find_vqs(), in order to 
request host-side virtio-queue. (This needs some more work...)

Feedback on this patch-set is appreciated, particularly on structure
and code-reuse between vhost.c and the host-side virtio-queue.
I'd also like some suggestions on how to handle the build configuration
better - currently there are some unnecessary build dependencies.

The patches are based on v3.7, and compile tested only.

Rusty, if you want to review this later, after the merge window closes,
let me know and I'll resend these patches later.

Thanks,
Sjur

Sjur Brændeland (11):
  vhost: Use struct vring in vhost_virtqueue
  vhost: Isolate reusable vring related functions
  virtio-ring: Introduce file virtio_ring_host
  virtio-ring: Refactor out the functions accessing user memory
  virtio-ring: Refactor move attributes to struct virtqueue
  virtio_ring: Move SMP macros to virtio_ring.h
  virtio-ring: Add Host side virtio-ring implementation
  virtio: Update vring_interrupt for host-side virtio queues
  virtio-ring: Add BUG_ON checking on host/guest ring type
  virtio: Add argument reversed to function find_vqs()
  remoteproc: Add support for host-virtqueues

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

 drivers/char/virtio_console.c  |3 +-
 drivers/lguest/lguest_device.c |5 +-
 drivers/net/caif/Kconfig   |8 +
 drivers/net/caif/Makefile  |3 +
 drivers/net/caif/caif_virtio.c |  482 
 drivers/net/virtio_net.c   |3 +-
 drivers/remoteproc/remoteproc_virtio.c |   18 +-
 drivers/rpmsg/virtio_rpmsg_bus.c   |2 +-
 drivers/s390/kvm/kvm_virtio.c  |5 +-
 drivers/scsi/virtio_scsi.c |2 +-
 drivers/vhost/Kconfig  |2 +
 drivers/vhost/net.c|4 +-
 drivers/vhost/vhost.c  |  272 +++---
 drivers/vhost/vhost.h  |   14 +-
 drivers/virtio/Kconfig |3 +
 drivers/virtio/Makefile|1 +
 drivers/virtio/virtio_balloon.c|3 +-
 drivers/virtio/virtio_mmio.c   |5 +-
 drivers/virtio/virtio_pci.c|3 +-
 drivers/virtio/virtio_ring.c   |   50 ++---
 drivers/virtio/virtio_ring_host.c  |  345 +++
 include/linux/virtio.h |6 +
 include/linux/virtio_caif.h|   25 ++
 include/linux/virtio_config.h  |7 +-
 include/linux/virtio_ring.h|   77 +-
 include/uapi/linux/virtio_ids.h|1 +
 26 files changed, 1120 insertions(+), 229 deletions(-)
 create mode 100644 drivers/net/caif/caif_virtio.c
 create mode 100644 drivers/virtio/virtio_ring_host.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

[RFCv2 01/12] vhost: Use struct vring in vhost_virtqueue

2012-12-05 Thread Sjur Brændeland
Pull out common vring attributes from vhost_virtqueue to a new
struct vring_host. This allows for reuse of data definitions
between vhost and virtio queue when host-side virtio queue is
introduced. Also unsigned long is replaced with ulong a couple
of places.

Signed-off-by: Sjur Brændeland sjur.brandel...@stericsson.com
---
 drivers/vhost/net.c |4 +-
 drivers/vhost/vhost.c   |  213 +++
 drivers/vhost/vhost.h   |   14 +---
 include/linux/virtio_ring.h |   13 +++
 4 files changed, 130 insertions(+), 114 deletions(-)

diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 072cbba..8fc1869 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -182,7 +182,7 @@ static void handle_tx(struct vhost_net *net)
if (unlikely(head  0))
break;
/* Nothing new?  Wait for eventfd to tell us they refilled. */
-   if (head == vq-num) {
+   if (head == vq-hst.vr.num) {
int num_pends;
 
wmem = atomic_read(sock-sk-sk_wmem_alloc);
@@ -329,7 +329,7 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
d = vhost_get_vq_desc(vq-dev, vq, vq-iov + seg,
  ARRAY_SIZE(vq-iov) - seg, out,
  in, log, log_num);
-   if (d == vq-num) {
+   if (d == vq-hst.vr.num) {
r = 0;
goto err;
}
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 99ac2cb..0a676f1 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -12,6 +12,7 @@
  */
 
 #include linux/eventfd.h
+#include linux/types.h
 #include linux/vhost.h
 #include linux/virtio_net.h
 #include linux/mm.h
@@ -39,8 +40,10 @@ enum {
 
 static unsigned vhost_zcopy_mask __read_mostly;
 
-#define vhost_used_event(vq) ((u16 __user *)vq-avail-ring[vq-num])
-#define vhost_avail_event(vq) ((u16 __user *)vq-used-ring[vq-num])
+#define vhost_used_event(vq) ((u16 __user *) \
+   vq-hst.vr.avail-ring[vq-hst.vr.num])
+#define vhost_avail_event(vq) ((u16 __user *)\
+   vq-hst.vr.used-ring[vq-hst.vr.num])
 
 static void vhost_poll_func(struct file *file, wait_queue_head_t *wqh,
poll_table *pt)
@@ -57,7 +60,7 @@ static int vhost_poll_wakeup(wait_queue_t *wait, unsigned 
mode, int sync,
 {
struct vhost_poll *poll = container_of(wait, struct vhost_poll, wait);
 
-   if (!((unsigned long)key  poll-mask))
+   if (!((ulong)key  poll-mask))
return 0;
 
vhost_poll_queue(poll);
@@ -75,7 +78,7 @@ void vhost_work_init(struct vhost_work *work, vhost_work_fn_t 
fn)
 
 /* Init poll structure */
 void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
-unsigned long mask, struct vhost_dev *dev)
+ulong mask, struct vhost_dev *dev)
 {
init_waitqueue_func_entry(poll-wait, vhost_poll_wakeup);
init_poll_funcptr(poll-table, vhost_poll_func);
@@ -89,7 +92,7 @@ void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t 
fn,
  * keep a reference to a file until after vhost_poll_stop is called. */
 void vhost_poll_start(struct vhost_poll *poll, struct file *file)
 {
-   unsigned long mask;
+   ulong mask;
 
mask = file-f_op-poll(file, poll-table);
if (mask)
@@ -139,7 +142,7 @@ void vhost_poll_flush(struct vhost_poll *poll)
 
 void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work)
 {
-   unsigned long flags;
+   ulong flags;
 
spin_lock_irqsave(dev-work_lock, flags);
if (list_empty(work-node)) {
@@ -158,13 +161,13 @@ void vhost_poll_queue(struct vhost_poll *poll)
 static void vhost_vq_reset(struct vhost_dev *dev,
   struct vhost_virtqueue *vq)
 {
-   vq-num = 1;
-   vq-desc = NULL;
-   vq-avail = NULL;
-   vq-used = NULL;
-   vq-last_avail_idx = 0;
-   vq-avail_idx = 0;
-   vq-last_used_idx = 0;
+   vq-hst.vr.num = 1;
+   vq-hst.vr.desc = NULL;
+   vq-hst.vr.avail = NULL;
+   vq-hst.vr.used = NULL;
+   vq-hst.last_avail_idx = 0;
+   vq-hst.avail_idx = 0;
+   vq-hst.last_used_idx = 0;
vq-signalled_used = 0;
vq-signalled_used_valid = false;
vq-used_flags = 0;
@@ -489,13 +492,13 @@ void vhost_dev_cleanup(struct vhost_dev *dev, bool locked)
dev-mm = NULL;
 }
 
-static int log_access_ok(void __user *log_base, u64 addr, unsigned long sz)
+static int log_access_ok(void __user *log_base, u64 addr, ulong sz)
 {
u64 a = addr / VHOST_PAGE_SIZE / 8;
 
/* Make sure 64 bit math will not overflow. */
-   if (a  ULONG_MAX - (unsigned long)log_base ||
-   a + (unsigned long)log_base  ULONG_MAX)
+   if (a  ULONG_MAX - (ulong)log_base ||
+   a + (ulong)log_base  ULONG_MAX)
return 0;
 

[RFCv2 02/12] vhost: Isolate reusable vring related functions

2012-12-05 Thread Sjur Brændeland
Prepare for moving virtio ring code out to a separate
file by isolating vring related functions. The function
vring_add_used_user() and vring_avail_desc_user() that
are handling virtio rings from user space are prepared
to be moved out.

Signed-off-by: Sjur Brændeland sjur.brandel...@stericsson.com
---
 drivers/vhost/vhost.c |  119 
 1 files changed, 69 insertions(+), 50 deletions(-)

diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 0a676f1..5e91048 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1100,7 +1100,7 @@ static int translate_desc(struct vhost_dev *dev, u64 
addr, u32 len,
 /* Each buffer in the virtqueues is actually a chain of descriptors.  This
  * function returns the next descriptor in the chain,
  * or -1U if we're at the end. */
-static unsigned next_desc(struct vring_desc *desc)
+unsigned vring_next_desc(struct vring_desc *desc)
 {
unsigned int next;
 
@@ -1202,46 +1202,29 @@ static int get_indirect(struct vhost_dev *dev, struct 
vhost_virtqueue *vq,
}
*out_num += ret;
}
-   } while ((i = next_desc(desc)) != -1);
+   } while ((i = vring_next_desc(desc)) != -1);
return 0;
 }
 
-/* This looks in the virtqueue and for the first available buffer, and converts
- * it to an iovec for convenient access.  Since descriptors consist of some
- * number of output then some number of input descriptors, it's actually two
- * iovecs, but we pack them into one and note how many of each there were.
- *
- * This function returns the descriptor number found, or vq-num (which is
- * never a valid descriptor number) if none was found.  A negative code is
- * returned on error. */
-int vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
- struct iovec iov[], unsigned int iov_size,
- unsigned int *out_num, unsigned int *in_num,
- struct vhost_log *log, unsigned int *log_num)
+static int vring_avail_desc_user(struct vring_host *vh)
 {
-   struct vring_desc desc;
-   unsigned int i, head, found = 0;
+   int head;
u16 last_avail_idx;
-   int ret;
 
/* Check it isn't doing very strange things with descriptor numbers. */
-   last_avail_idx = vq-hst.last_avail_idx;
-   if (unlikely(__get_user(vq-hst.avail_idx, vq-hst.vr.avail-idx))) {
-   vq_err(vq, Failed to access avail idx at %p\n,
-  vq-hst.vr.avail-idx);
+   last_avail_idx = vh-last_avail_idx;
+   if (unlikely(__get_user(vh-avail_idx, vh-vr.avail-idx))) {
+   pr_debug(Failed to access avail idx at %p\n,
+  vh-vr.avail-idx);
return -EFAULT;
}
 
-   if (unlikely((u16)(vq-hst.avail_idx -
-  last_avail_idx)  vq-hst.vr.num)) {
-   vq_err(vq, Guest moved used index from %u to %u,
-  last_avail_idx, vq-hst.avail_idx);
+   if (unlikely((u16)(vh-avail_idx - last_avail_idx)  vh-vr.num))
return -EFAULT;
-   }
 
/* If there's nothing new since last we looked, return invalid. */
-   if (vq-hst.avail_idx == last_avail_idx)
-   return vq-hst.vr.num;
+   if (vh-avail_idx == last_avail_idx)
+   return vh-vr.num;
 
/* Only get avail ring entries after they have been exposed by guest. */
smp_rmb();
@@ -1249,22 +1232,46 @@ int vhost_get_vq_desc(struct vhost_dev *dev, struct 
vhost_virtqueue *vq,
/* Grab the next descriptor number they're advertising, and increment
 * the index we've seen. */
if (unlikely(__get_user(head,
-   vq-hst.vr.avail-ring[last_avail_idx %
-   vq-hst.vr.num]))) {
-   vq_err(vq, Failed to read head: idx %d address %p\n,
-  last_avail_idx,
-  vq-hst.vr.avail-ring[last_avail_idx %
-  vq-hst.vr.num]);
+   vh-vr.avail-ring[last_avail_idx %
+   vh-vr.num]))) {
+   pr_debug(Failed to read head: idx %d address %p\n,
+last_avail_idx,
+  vh-vr.avail-ring[last_avail_idx %
+  vh-vr.num]);
return -EFAULT;
}
 
/* If their number is silly, that's an error. */
-   if (unlikely(head = vq-hst.vr.num)) {
-   vq_err(vq, Guest says index %u  %u is available,
-  head, vq-hst.vr.num);
+   if (unlikely(head = vh-vr.num)) {
+   pr_debug(Guest says index %u  %u is available,
+  head, vh-vr.num);
return -EINVAL;
}
 
+   return head;
+}
+
+/* This looks in the virtqueue 

[RFCv2 03/12] virtio-ring: Introduce file virtio_ring_host

2012-12-05 Thread Sjur Brændeland
Move host-side virtio ring functions to file virtio_ring_host.c
The functions vring_avail_desc_user(), vring_add_used_user() and
vring_next_desc() are moved from vhost.c to the new file
virtio_ring_host.c. (The functions are copied as is without any changes)

Signed-off-by: Sjur Brændeland sjur.brandel...@stericsson.com
---
 drivers/vhost/Kconfig |2 +
 drivers/vhost/vhost.c |   92 -
 drivers/virtio/Kconfig|3 +
 drivers/virtio/Makefile   |1 +
 drivers/virtio/virtio_ring_host.c |  117 +
 include/linux/virtio_ring.h   |8 +++
 6 files changed, 131 insertions(+), 92 deletions(-)
 create mode 100644 drivers/virtio/virtio_ring_host.c

diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig
index 202bba6..5bfdaa9 100644
--- a/drivers/vhost/Kconfig
+++ b/drivers/vhost/Kconfig
@@ -1,4 +1,6 @@
 config VHOST_NET
+   select VIRTIO_RING_HOST
+   select VIRTIO
tristate Host kernel accelerator for virtio net (EXPERIMENTAL)
depends on NET  EVENTFD  (TUN || !TUN)  (MACVTAP || !MACVTAP)  
EXPERIMENTAL
---help---
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 5e91048..6634f0a 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1097,27 +1097,6 @@ static int translate_desc(struct vhost_dev *dev, u64 
addr, u32 len,
return ret;
 }
 
-/* Each buffer in the virtqueues is actually a chain of descriptors.  This
- * function returns the next descriptor in the chain,
- * or -1U if we're at the end. */
-unsigned vring_next_desc(struct vring_desc *desc)
-{
-   unsigned int next;
-
-   /* If this descriptor says it doesn't chain, we're done. */
-   if (!(desc-flags  VRING_DESC_F_NEXT))
-   return -1U;
-
-   /* Check they're not leading us off end of descriptors. */
-   next = desc-next;
-   /* Make sure compiler knows to grab that: we don't want it changing! */
-   /* We will use the result as an index in an array, so most
-* architectures only need a compiler barrier here. */
-   read_barrier_depends();
-
-   return next;
-}
-
 static int get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
struct iovec iov[], unsigned int iov_size,
unsigned int *out_num, unsigned int *in_num,
@@ -1206,51 +1185,6 @@ static int get_indirect(struct vhost_dev *dev, struct 
vhost_virtqueue *vq,
return 0;
 }
 
-static int vring_avail_desc_user(struct vring_host *vh)
-{
-   int head;
-   u16 last_avail_idx;
-
-   /* Check it isn't doing very strange things with descriptor numbers. */
-   last_avail_idx = vh-last_avail_idx;
-   if (unlikely(__get_user(vh-avail_idx, vh-vr.avail-idx))) {
-   pr_debug(Failed to access avail idx at %p\n,
-  vh-vr.avail-idx);
-   return -EFAULT;
-   }
-
-   if (unlikely((u16)(vh-avail_idx - last_avail_idx)  vh-vr.num))
-   return -EFAULT;
-
-   /* If there's nothing new since last we looked, return invalid. */
-   if (vh-avail_idx == last_avail_idx)
-   return vh-vr.num;
-
-   /* Only get avail ring entries after they have been exposed by guest. */
-   smp_rmb();
-
-   /* Grab the next descriptor number they're advertising, and increment
-* the index we've seen. */
-   if (unlikely(__get_user(head,
-   vh-vr.avail-ring[last_avail_idx %
-   vh-vr.num]))) {
-   pr_debug(Failed to read head: idx %d address %p\n,
-last_avail_idx,
-  vh-vr.avail-ring[last_avail_idx %
-  vh-vr.num]);
-   return -EFAULT;
-   }
-
-   /* If their number is silly, that's an error. */
-   if (unlikely(head = vh-vr.num)) {
-   pr_debug(Guest says index %u  %u is available,
-  head, vh-vr.num);
-   return -EINVAL;
-   }
-
-   return head;
-}
-
 /* This looks in the virtqueue and for the first available buffer, and converts
  * it to an iovec for convenient access.  Since descriptors consist of some
  * number of output then some number of input descriptors, it's actually two
@@ -1352,32 +1286,6 @@ void vhost_discard_vq_desc(struct vhost_virtqueue *vq, 
int n)
vq-hst.last_avail_idx -= n;
 }
 
-struct vring_used_elem *vring_add_used_user(struct vring_host *vh,
-unsigned int head, int len)
-{
-   struct vring_used_elem  *used;
-
-   /* The virtqueue contains a ring of used buffers.  Get a pointer to the
-* next entry in that used ring. */
-   used = vh-vr.used-ring[vh-last_used_idx % vh-vr.num];
-   if (__put_user(head, used-id)) {
-   pr_debug(Failed to write used id);
-   

[RFCv2 04/12] virtio-ring: Refactor out the functions accessing user memory

2012-12-05 Thread Sjur Brændeland
Isolate the access to user-memory in separate inline
functions. This open up for reuse from host-side virtioqueue
implementation accessing virtio-ring in kernel space.

Signed-off-by: Sjur Brændeland sjur.brandel...@stericsson.com
---
 drivers/virtio/virtio_ring_host.c |   81 ++---
 1 files changed, 57 insertions(+), 24 deletions(-)

diff --git a/drivers/virtio/virtio_ring_host.c 
b/drivers/virtio/virtio_ring_host.c
index 192b838..0750099 100644
--- a/drivers/virtio/virtio_ring_host.c
+++ b/drivers/virtio/virtio_ring_host.c
@@ -18,44 +18,45 @@
 #include linux/virtio_ring.h
 #include linux/module.h
 #include linux/uaccess.h
+#include linux/kconfig.h
 
 MODULE_LICENSE(GPL);
 
-struct vring_used_elem *vring_add_used_user(struct vring_host *vh,
-unsigned int head, int len)
+
+static inline struct vring_used_elem *_vring_add_used(struct vring_host *vh,
+ u32 head, u32 len,
+ bool (*cpy)(void *dst,
+ void *src,
+ size_t s),
+ void (*wbarrier)(void))
 {
struct vring_used_elem  *used;
+   u16 last_used;
 
/* The virtqueue contains a ring of used buffers.  Get a pointer to the
 * next entry in that used ring. */
-   used = vh-vr.used-ring[vh-last_used_idx % vh-vr.num];
-   if (__put_user(head, used-id)) {
-   pr_debug(Failed to write used id);
+   used = vh-vr.used-ring[vh-last_used_idx  (vh-vr.num - 1)];
+   if (!cpy(used-id, head, sizeof(used-id)) ||
+   !cpy(used-len, len, sizeof(used-len)))
return NULL;
-   }
-   if (__put_user(len, used-len)) {
-   pr_debug(Failed to write used len);
+   wbarrier();
+   last_used = vh-last_used_idx + 1;
+   if (!cpy(vh-vr.used-idx, last_used, sizeof(vh-vr.used-idx)))
return NULL;
-   }
-   /* Make sure buffer is written before we update index. */
-   smp_wmb();
-   if (__put_user(vh-last_used_idx + 1, vh-vr.used-idx)) {
-   pr_debug(Failed to increment used idx);
-   return NULL;
-   }
-   vh-last_used_idx++;
+   vh-last_used_idx = last_used;
return used;
 }
-EXPORT_SYMBOL(vring_add_used_user);
 
-int vring_avail_desc_user(struct vring_host *vh)
+static inline int _vring_avail_desc(struct vring_host *vh,
+   bool (*get)(u16 *dst, u16 *src),
+   void (*read_barrier)(void))
 {
-   int head;
+   u16 head;
u16 last_avail_idx;
 
/* Check it isn't doing very strange things with descriptor numbers. */
last_avail_idx = vh-last_avail_idx;
-   if (unlikely(__get_user(vh-avail_idx, vh-vr.avail-idx))) {
+   if (unlikely(!get(vh-avail_idx, vh-vr.avail-idx))) {
pr_debug(Failed to access avail idx at %p\n,
   vh-vr.avail-idx);
return -EFAULT;
@@ -69,13 +70,12 @@ int vring_avail_desc_user(struct vring_host *vh)
return vh-vr.num;
 
/* Only get avail ring entries after they have been exposed by guest. */
-   smp_rmb();
+   read_barrier();
 
/* Grab the next descriptor number they're advertising, and increment
 * the index we've seen. */
-   if (unlikely(__get_user(head,
-   vh-vr.avail-ring[last_avail_idx %
-   vh-vr.num]))) {
+   if (unlikely(!get(head, vh-vr.avail-ring[last_avail_idx 
+(vh-vr.num - 1)]))) {
pr_debug(Failed to read head: idx %d address %p\n,
 last_avail_idx,
   vh-vr.avail-ring[last_avail_idx %
@@ -92,6 +92,39 @@ int vring_avail_desc_user(struct vring_host *vh)
 
return head;
 }
+
+static inline void smp_write_barrier(void)
+{
+   smp_wmb();
+}
+
+static inline void smp_read_barrier(void)
+{
+   smp_rmb();
+}
+
+static inline bool userspace_cpy_to(void  *dst, void *src, size_t s)
+{
+   return __copy_to_user(dst, src, s) == 0;
+}
+
+static inline bool userspace_get(u16 *dst, u16 *src)
+{
+   return __get_user(*dst, src);
+}
+
+struct vring_used_elem *vring_add_used_user(struct vring_host *vh,
+   unsigned int head, int len)
+{
+   return _vring_add_used(vh, head, len, userspace_cpy_to,
+  smp_write_barrier);
+}
+EXPORT_SYMBOL(vring_add_used_user);
+
+int vring_avail_desc_user(struct vring_host *vh)
+{
+   return _vring_avail_desc(vh, userspace_get, smp_read_barrier);
+}
 EXPORT_SYMBOL(vring_avail_desc_user);
 
 /* Each buffer in the virtqueues is 

[RFCv2 05/12] virtio-ring: Refactor move attributes to struct virtqueue

2012-12-05 Thread Sjur Brændeland
Attributes 'weak_barriers' and 'notify' are moved
from struct vring_virtqueue to struct virtqueue.

Signed-off-by: Sjur Brændeland sjur.brandel...@stericsson.com
---
 drivers/virtio/virtio_ring.c |   20 +++-
 include/linux/virtio.h   |4 
 2 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index ffd7e7d..6aa76b4 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -31,11 +31,11 @@
  * barriers, because mandatory barriers control MMIO effects on accesses
  * through relaxed memory I/O windows (which virtio-pci does not use). */
 #define virtio_mb(vq) \
-   do { if ((vq)-weak_barriers) smp_mb(); else mb(); } while(0)
+   do { if ((vq)-vq.weak_barriers) smp_mb(); else mb(); } while (0)
 #define virtio_rmb(vq) \
-   do { if ((vq)-weak_barriers) smp_rmb(); else rmb(); } while(0)
+   do { if ((vq)-vq.weak_barriers) smp_rmb(); else rmb(); } while (0)
 #define virtio_wmb(vq) \
-   do { if ((vq)-weak_barriers) smp_wmb(); else wmb(); } while(0)
+   do { if ((vq)-vq.weak_barriers) smp_wmb(); else wmb(); } while (0)
 #else
 /* We must force memory ordering even if guest is UP since host could be
  * running on another CPU, but SMP barriers are defined to barrier() in that
@@ -81,9 +81,6 @@ struct vring_virtqueue
/* Actual memory layout for this queue */
struct vring vring;
 
-   /* Can we use weak barriers? */
-   bool weak_barriers;
-
/* Other side has made a mess, don't try any more. */
bool broken;
 
@@ -101,9 +98,6 @@ struct vring_virtqueue
/* Last used index we've seen. */
u16 last_used_idx;
 
-   /* How to notify other side. FIXME: commonalize hcalls! */
-   void (*notify)(struct virtqueue *vq);
-
 #ifdef DEBUG
/* They're supposed to lock for us. */
unsigned int in_use;
@@ -236,7 +230,7 @@ int virtqueue_add_buf(struct virtqueue *_vq,
 * there are outgoing parts to the buffer.  Presumably the
 * host should service the ring ASAP. */
if (out)
-   vq-notify(vq-vq);
+   vq-vq.notify(vq-vq);
END_USE(vq);
return -ENOSPC;
}
@@ -348,7 +342,7 @@ void virtqueue_notify(struct virtqueue *_vq)
struct vring_virtqueue *vq = to_vvq(_vq);
 
/* Prod other side to tell it about changes. */
-   vq-notify(_vq);
+   vq-vq.notify(_vq);
 }
 EXPORT_SYMBOL_GPL(virtqueue_notify);
 
@@ -647,8 +641,8 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
vq-vq.name = name;
vq-vq.num_free = num;
vq-vq.index = index;
-   vq-notify = notify;
-   vq-weak_barriers = weak_barriers;
+   vq-vq.notify = notify;
+   vq-vq.weak_barriers = weak_barriers;
vq-broken = false;
vq-last_used_idx = 0;
vq-num_added = 0;
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index 25fa1a6..f513ba8 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -13,11 +13,13 @@
  * virtqueue - a queue to register buffers for sending or receiving.
  * @list: the chain of virtqueues for this device
  * @callback: the function to call when buffers are consumed (can be NULL).
+ * @notify: the function to notify the other side (can be NULL)
  * @name: the name of this virtqueue (mainly for debugging)
  * @vdev: the virtio device this queue was created for.
  * @priv: a pointer for the virtqueue implementation to use.
  * @index: the zero-based ordinal number for this queue.
  * @num_free: number of elements we expect to be able to fit.
+ * @weak_barriers: indicate if we can use weak memory barriers.
  *
  * A note on @num_free: with indirect buffers, each buffer needs one
  * element in the queue, otherwise a buffer will need one element per
@@ -26,11 +28,13 @@
 struct virtqueue {
struct list_head list;
void (*callback)(struct virtqueue *vq);
+   void (*notify)(struct virtqueue *vq);
const char *name;
struct virtio_device *vdev;
unsigned int index;
unsigned int num_free;
void *priv;
+   bool weak_barriers;
 };
 
 int virtqueue_add_buf(struct virtqueue *vq,
-- 
1.7.5.4

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

[RFCv2 06/12] virtio_ring: Move SMP macros to virtio_ring.h

2012-12-05 Thread Sjur Brændeland
Move macros from virtio_ring.c to virtio_ring.h so that
they can be used outside the file.

Signed-off-by: Sjur Brændeland sjur.brandel...@stericsson.com
---
 drivers/virtio/virtio_ring.c |   21 -
 include/linux/virtio_ring.h  |   20 
 2 files changed, 20 insertions(+), 21 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 6aa76b4..ead47d7 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -24,27 +24,6 @@
 #include linux/module.h
 #include linux/hrtimer.h
 
-/* virtio guest is communicating with a virtual device that actually runs on
- * a host processor.  Memory barriers are used to control SMP effects. */
-#ifdef CONFIG_SMP
-/* Where possible, use SMP barriers which are more lightweight than mandatory
- * barriers, because mandatory barriers control MMIO effects on accesses
- * through relaxed memory I/O windows (which virtio-pci does not use). */
-#define virtio_mb(vq) \
-   do { if ((vq)-vq.weak_barriers) smp_mb(); else mb(); } while (0)
-#define virtio_rmb(vq) \
-   do { if ((vq)-vq.weak_barriers) smp_rmb(); else rmb(); } while (0)
-#define virtio_wmb(vq) \
-   do { if ((vq)-vq.weak_barriers) smp_wmb(); else wmb(); } while (0)
-#else
-/* We must force memory ordering even if guest is UP since host could be
- * running on another CPU, but SMP barriers are defined to barrier() in that
- * configuration. So fall back to mandatory barriers instead. */
-#define virtio_mb(vq) mb()
-#define virtio_rmb(vq) rmb()
-#define virtio_wmb(vq) wmb()
-#endif
-
 #ifdef DEBUG
 /* For development, we want to crash whenever the ring is screwed. */
 #define BAD_RING(_vq, fmt, args...)\
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h
index 6c9b871..1a4023b 100644
--- a/include/linux/virtio_ring.h
+++ b/include/linux/virtio_ring.h
@@ -42,4 +42,24 @@ int vring_avail_desc_user(struct vring_host *vh);
 struct vring_used_elem *vring_add_used_user(struct vring_host *vh,
unsigned int head, int len);
 
+/* virtio guest is communicating with a virtual device that actually runs on
+ * a host processor.  Memory barriers are used to control SMP effects. */
+#ifdef CONFIG_SMP
+/* Where possible, use SMP barriers which are more lightweight than mandatory
+ * barriers, because mandatory barriers control MMIO effects on accesses
+ * through relaxed memory I/O windows (which virtio-pci does not use). */
+#define virtio_mb(vq) \
+   do { if ((vq)-vq.weak_barriers) smp_mb(); else mb(); } while (0)
+#define virtio_rmb(vq) \
+   do { if ((vq)-vq.weak_barriers) smp_rmb(); else rmb(); } while (0)
+#define virtio_wmb(vq) \
+   do { if ((vq)-vq.weak_barriers) smp_wmb(); else wmb(); } while (0)
+#else
+/* We must force memory ordering even if guest is UP since host could be
+ * running on another CPU, but SMP barriers are defined to barrier() in that
+ * configuration. So fall back to mandatory barriers instead. */
+#define virtio_mb(vq) mb()
+#define virtio_rmb(vq) rmb()
+#define virtio_wmb(vq) wmb()
+#endif
 #endif /* _LINUX_VIRTIO_RING_H */
-- 
1.7.5.4

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

[RFCv2 07/12] virtio-ring: Add Host side virtio-ring implementation

2012-12-05 Thread Sjur Brændeland
Introduce a host-side virtio queue implementation. The function
vring_new_host_virtqueue(), virtqueue_add_buf_to_used()
virtqueue_next_avail_desc() are added to virtio_ring_host.c

Signed-off-by: Sjur Brændeland sjur.brandel...@stericsson.com
---
 drivers/virtio/virtio_ring_host.c |  195 +
 include/linux/virtio.h|2 +
 include/linux/virtio_ring.h   |   23 +
 3 files changed, 220 insertions(+), 0 deletions(-)

diff --git a/drivers/virtio/virtio_ring_host.c 
b/drivers/virtio/virtio_ring_host.c
index 0750099..570e11e 100644
--- a/drivers/virtio/virtio_ring_host.c
+++ b/drivers/virtio/virtio_ring_host.c
@@ -19,10 +19,32 @@
 #include linux/module.h
 #include linux/uaccess.h
 #include linux/kconfig.h
+#include linux/slab.h
 
 MODULE_LICENSE(GPL);
 
 
+struct vring_host_virtqueue {
+   struct virtqueue vq;
+
+   /* Actual memory layout for this queue */
+   struct vring_host vring;
+
+   /* Other side has made a mess, don't try any more. */
+   bool broken;
+};
+
+#define to_vvq(_vq) container_of(_vq, struct vring_host_virtqueue, vq)
+
+#define BAD_RING(_vq, fmt, args...)\
+   do {\
+   dev_err(_vq-vq.vdev-dev, \
+   %s:fmt, (_vq)-vq.name, ##args);  \
+   (_vq)-broken = true;   \
+   } while (0)
+#define START_USE(vq)
+#define END_USE(vq)
+
 static inline struct vring_used_elem *_vring_add_used(struct vring_host *vh,
  u32 head, u32 len,
  bool (*cpy)(void *dst,
@@ -148,3 +170,176 @@ unsigned vring_next_desc(struct vring_desc *desc)
return next;
 }
 EXPORT_SYMBOL(vring_next_desc);
+
+struct virtqueue *vring_new_host_virtqueue(unsigned int index,
+ unsigned int num,
+ unsigned int vring_align,
+ struct virtio_device *vdev,
+ bool weak_barriers,
+ void *pages,
+ void (*notify)(struct virtqueue *),
+ void (*callback)(struct virtqueue *),
+ const char *name)
+{
+   struct vring_host_virtqueue *vq;
+
+   /* We assume num is a power of 2. */
+   if (num  (num - 1)) {
+   dev_warn(vdev-dev, Bad virtqueue length %u\n, num);
+   return NULL;
+   }
+
+   vq = kmalloc(sizeof(*vq), GFP_KERNEL);
+   if (!vq)
+   return NULL;
+
+   vring_init(vq-vring.vr, num, pages, vring_align);
+   vq-vq.callback = callback;
+   vq-vq.vdev = vdev;
+   vq-vq.name = name;
+   vq-vq.num_free = num;
+   vq-vq.index = index;
+   vq-vq.weak_barriers = weak_barriers;
+   vq-vq.notify = notify;
+   vq-broken = false;
+   vq-vq.reversed = true;
+   list_add_tail(vq-vq.list, vdev-vqs);
+   /* FIX: What about no callback, should we tell pair not to bother us? */
+   return vq-vq;
+}
+EXPORT_SYMBOL_GPL(vring_new_host_virtqueue);
+
+static inline bool _kernel_cpy_to(void  *dst, void *src, size_t s)
+{
+   memcpy(dst, src, s);
+   return true;
+}
+
+static inline bool _kernel_get(u16 *dst, u16 *src)
+{
+   *dst = *src;
+   return true;
+}
+
+static inline void _read_barrier(void)
+{
+   rmb();
+}
+
+/**
+ * virtqueue_next_avail_desc - get the next available descriptor
+ * @_vq: the struct virtqueue we're talking about
+ * @head: index of the descriptor in the ring
+ *
+ * Look for the next available descriptor in the available ring.
+ * Return NULL if nothing new in the available.
+ */
+struct vring_desc *virtqueue_next_avail_desc(struct virtqueue *_vq,
+   int *head)
+{
+   struct vring_host_virtqueue *vq = to_vvq(_vq);
+   struct vring_desc *desc = NULL;
+   int hd = -1;
+
+   BUG_ON(!vq-vq.reversed);
+   if (unlikely(vq-broken))
+   goto out;
+
+   START_USE(vq);
+   virtio_rmb(vq);
+
+   hd = _vring_avail_desc(vq-vring, _kernel_get, _read_barrier);
+   if (unlikely(hd  0)) {
+   BAD_RING(vq, Bad available descriptor avail:%d last:%d\n,
+vq-vring.avail_idx, vq-vring.last_avail_idx);
+   goto out;
+   }
+   if (likely(hd = vq-vring.vr.num))
+   goto out;
+
+   desc = vq-vring.vr.desc[hd];
+   vq-vring.last_avail_idx++;
+out:
+   *head = hd;
+   END_USE(vq);
+   return desc;
+}
+EXPORT_SYMBOL(virtqueue_next_avail_desc);
+
+/*
+ * virtqueue_next_linked_desc - get next linked descriptor from the ring
+ * @_vq: the struct virtqueue we're talking about
+ * @desc: current descriptor
+ *
+ * Each 

[RFCv2 08/12] virtio: Update vring_interrupt for host-side virtio queues

2012-12-05 Thread Sjur Brændeland
From: Sjur Brændeland sjur.brandel...@stericsson.com

Add an inline function for vring_interrupt that can handle
host side virtio queues.

Signed-off-by: Sjur Brændeland sjur.brandel...@stericsson.com
---
 drivers/virtio/virtio_ring.c |4 ++--
 include/linux/virtio_ring.h  |   13 -
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index ead47d7..67f7bcd 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -571,7 +571,7 @@ void *virtqueue_detach_unused_buf(struct virtqueue *_vq)
 }
 EXPORT_SYMBOL_GPL(virtqueue_detach_unused_buf);
 
-irqreturn_t vring_interrupt(int irq, void *_vq)
+irqreturn_t __vring_interrupt(int irq, void *_vq)
 {
struct vring_virtqueue *vq = to_vvq(_vq);
 
@@ -589,7 +589,7 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
 
return IRQ_HANDLED;
 }
-EXPORT_SYMBOL_GPL(vring_interrupt);
+EXPORT_SYMBOL_GPL(__vring_interrupt);
 
 struct virtqueue *vring_new_virtqueue(unsigned int index,
  unsigned int num,
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h
index 01c0f59..d0aa046 100644
--- a/include/linux/virtio_ring.h
+++ b/include/linux/virtio_ring.h
@@ -33,7 +33,18 @@ void vring_del_virtqueue(struct virtqueue *vq);
 /* Filter out transport-specific feature bits. */
 void vring_transport_features(struct virtio_device *vdev);
 
-irqreturn_t vring_interrupt(int irq, void *_vq);
+irqreturn_t __vring_interrupt(int irq, void *_vq);
+static inline irqreturn_t vring_interrupt(int irq, void *_vq)
+{
+   struct virtqueue *vq = _vq;
+   if (!vq-callback)
+   return IRQ_HANDLED;
+   if (vq-reversed) {
+   vq-callback(vq);
+   return IRQ_HANDLED;
+   }
+   return __vring_interrupt(irq, vq);
+}
 
 unsigned vring_next_desc(struct vring_desc *desc);
 
-- 
1.7.5.4

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

[RFCv2 09/12] virtio-ring: Add BUG_ON checking on host/guest ring type

2012-12-05 Thread Sjur Brændeland
From: Sjur Brændeland sjur.brandel...@stericsson.com

Add BUG_ON to ensure that the correct virtio queue type is
used for the virtqueue functions.
In addition the function virtqueue_kick_prepare() is changed so
that it always returns true if the virtio-ring is reversed.

Signed-off-by: Sjur Brændeland sjur.brandel...@stericsson.com
---
 drivers/virtio/virtio_ring.c |   11 +++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 67f7bcd..a6f38c1 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -176,6 +176,7 @@ int virtqueue_add_buf(struct virtqueue *_vq,
 
START_USE(vq);
 
+   BUG_ON(vq-vq.reversed);
BUG_ON(data == NULL);
 
 #ifdef DEBUG
@@ -282,6 +283,9 @@ bool virtqueue_kick_prepare(struct virtqueue *_vq)
u16 new, old;
bool needs_kick;
 
+   if (_vq-reversed)
+   return true;
+
START_USE(vq);
/* We need to expose available array entries before checking avail
 * event. */
@@ -346,6 +350,7 @@ static void detach_buf(struct vring_virtqueue *vq, unsigned 
int head)
 {
unsigned int i;
 
+   BUG_ON(vq-vq.reversed);
/* Clear data ptr. */
vq-data[head] = NULL;
 
@@ -395,6 +400,7 @@ void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int 
*len)
unsigned int i;
u16 last_used;
 
+   BUG_ON(vq-vq.reversed);
START_USE(vq);
 
if (unlikely(vq-broken)) {
@@ -457,6 +463,7 @@ EXPORT_SYMBOL_GPL(virtqueue_get_buf);
 void virtqueue_disable_cb(struct virtqueue *_vq)
 {
struct vring_virtqueue *vq = to_vvq(_vq);
+   BUG_ON(vq-vq.reversed);
 
vq-vring.avail-flags |= VRING_AVAIL_F_NO_INTERRUPT;
 }
@@ -477,6 +484,7 @@ bool virtqueue_enable_cb(struct virtqueue *_vq)
 {
struct vring_virtqueue *vq = to_vvq(_vq);
 
+   BUG_ON(vq-vq.reversed);
START_USE(vq);
 
/* We optimistically turn back on interrupts, then check if there was
@@ -515,6 +523,7 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *_vq)
struct vring_virtqueue *vq = to_vvq(_vq);
u16 bufs;
 
+   BUG_ON(vq-vq.reversed);
START_USE(vq);
 
/* We optimistically turn back on interrupts, then check if there was
@@ -551,6 +560,7 @@ void *virtqueue_detach_unused_buf(struct virtqueue *_vq)
unsigned int i;
void *buf;
 
+   BUG_ON(vq-vq.reversed);
START_USE(vq);
 
for (i = 0; i  vq-vring.num; i++) {
@@ -575,6 +585,7 @@ irqreturn_t __vring_interrupt(int irq, void *_vq)
 {
struct vring_virtqueue *vq = to_vvq(_vq);
 
+   BUG_ON(vq-vq.reversed);
if (!more_used(vq)) {
pr_debug(virtqueue interrupt with no work for %p\n, vq);
return IRQ_NONE;
-- 
1.7.5.4

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

[RFCv2 11/12] remoteproc: Add support for host-virtqueues

2012-12-05 Thread Sjur Brændeland
Create a virtio-queue in reversed direction if requested
by the virtio device. This is done by calling the function
vring_new_host_virtqueue().

Signed-off-by: Sjur Brændeland sjur.brandel...@stericsson.com
---
 drivers/remoteproc/remoteproc_virtio.c |   15 ---
 1 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_virtio.c 
b/drivers/remoteproc/remoteproc_virtio.c
index a825f67..5866b03 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -69,6 +69,7 @@ EXPORT_SYMBOL(rproc_vq_interrupt);
 
 static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
unsigned id,
+   bool revers,
void (*callback)(struct virtqueue *vq),
const char *name)
 {
@@ -106,8 +107,14 @@ static struct virtqueue *rp_find_vq(struct virtio_device 
*vdev,
 * Create the new vq, and tell virtio we're not interested in
 * the 'weak' smp barriers, since we're talking with a real device.
 */
-   vq = vring_new_virtqueue(id, len, rvring-align, vdev, false, addr,
-   rproc_virtio_notify, callback, name);
+   if (revers)
+   vq = vring_new_host_virtqueue(id, len, rvring-align, vdev,
+ false, addr, rproc_virtio_notify,
+ callback, name);
+   else
+   vq = vring_new_virtqueue(id, len, rvring-align, vdev, false,
+addr, rproc_virtio_notify, callback,
+name);
if (!vq) {
dev_err(dev, vring_new_virtqueue %s failed\n, name);
rproc_free_vring(rvring);
@@ -145,9 +152,11 @@ static int rproc_virtio_find_vqs(struct virtio_device 
*vdev, unsigned nvqs,
 {
struct rproc *rproc = vdev_to_rproc(vdev);
int i, ret;
+   bool revers;
 
for (i = 0; i  nvqs; ++i) {
-   vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i]);
+   revers = reversed ? reversed[i] : false;
+   vqs[i] = rp_find_vq(vdev, i, revers, callbacks[i], names[i]);
if (IS_ERR(vqs[i])) {
ret = PTR_ERR(vqs[i]);
goto error;
-- 
1.7.5.4

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

[RFCv2 12/12] caif_virtio: Introduce caif over virtio

2012-12-05 Thread Sjur Brændeland
From: Vikram ARV vikram@stericsson.com

caif_virtio is using the remoteproc and virtio framework
for communicating with the modem. The CAIF link layer
device is registered as a network device.

CAIF over virtio uses the virtio rings in both directions,
and request a reversed virtio queue in the RX direction.

Signed-off-by: Vikram ARV vikram@stericsson.com
Signed-off-by: Sjur Brændeland sjur.brandel...@stericsson.com
---
 drivers/net/caif/Kconfig|8 +
 drivers/net/caif/Makefile   |3 +
 drivers/net/caif/caif_virtio.c  |  482 +++
 include/linux/virtio_caif.h |   24 ++
 include/uapi/linux/virtio_ids.h |1 +
 5 files changed, 518 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..a1279d5 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 VIRTIO
+   default m
+   ---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..94efd21
--- /dev/null
+++ b/drivers/net/caif/caif_virtio.c
@@ -0,0 +1,482 @@
+/*
+ * 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
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME :%s/%d  fmt,  __func__, __LINE__
+#include linux/module.h
+#include linux/virtio.h
+#include linux/virtio_ids.h
+#include linux/virtio_config.h
+#include linux/dma-mapping.h
+#include linux/netdevice.h
+#include linux/if_arp.h
+#include linux/spinlock.h
+#include linux/virtio_caif.h
+#include linux/virtio_ring.h
+#include net/caif/caif_dev.h
+
+MODULE_LICENSE(GPL v2);
+MODULE_AUTHOR(Vicram Arv vikram@stericsson.com);
+MODULE_DESCRIPTION(Virtio CAIF Driver);
+
+/*
+ * struct cfv_info - Caif Virtio control structure
+ * @cfdev: caif common header
+ * @vdev:  Associated virtio device
+ * @vq_rx: rx/downlink virtqueue
+ * @vq_tx: tx/uplink virtqueue
+ * @ndev:  associated netdevice
+ * @queued_tx: number of buffers queued in the tx virtqueue
+ * @watermark_tx: indicates number of buffers the tx queue
+ * should shrink to to unblock datapath
+ * @tx_lock:   protects vq_tx to allow concurrent senders
+ * @tx_hr: transmit headroom
+ * @rx_hr: receive headroom
+ * @tx_tr: transmit tailroom
+ * @rx_tr: receive tailroom
+ * @mtu:   transmit max size
+ * @mru:   receive max size
+ */
+struct cfv_info {
+   struct caif_dev_common cfdev;
+   struct virtio_device *vdev;
+   struct virtqueue *vq_rx;
+   struct virtqueue *vq_tx;
+   struct net_device *ndev;
+   unsigned int queued_tx;
+   unsigned int watermark_tx;
+   /* Protect access to vq_tx */
+   spinlock_t tx_lock;
+   /* Copied from Virtio config space */
+   u16 tx_hr;
+   u16 rx_hr;
+   u16 tx_tr;
+   u16 rx_tr;
+   u32 mtu;
+   u32 mru;
+};
+
+/*
+ * struct token_info - maintains Transmit buffer data handle
+ * @size:  size of transmit buffer
+ * @dma_handle: handle to allocated dma device memory area
+ * @vaddr: virtual address mapping to allocated memory area
+ */
+struct token_info {
+   size_t size;
+   u8 *vaddr;
+   dma_addr_t dma_handle;
+};
+
+/* Default if virtio config space is unavailable */
+#define CFV_DEF_MTU_SIZE 4096
+#define CFV_DEF_HEADROOM 0
+#define CFV_DEF_TAILROOM 0
+
+/* Require IP header to be 4-byte aligned. */
+#define IP_HDR_ALIGN 4
+
+/*
+ * virtqueue_next_desc - get next available or linked descriptor
+ * @_vq: the struct virtqueue we're talking about
+ * @desc: current descriptor.
+ * @head: on return it is filled by the descriptor index in case of
+ * available descriptor was returned, or -1 in case of linked
+ * descriptor.
+ *
+ * The function is to be used as an iterator through received descriptors.
+ */
+static struct vring_desc *virtqueue_next_desc(struct virtqueue *_vq,
+ struct 

Re: [PATCHv5] virtio-spec: virtio network device RFS support

2012-12-05 Thread Ben Hutchings
On Mon, 2012-12-03 at 12:58 +0200, Michael S. Tsirkin wrote:
 Add RFS support to virtio network device.
 Add a new feature flag VIRTIO_NET_F_RFS for this feature, a new
 configuration field max_virtqueue_pairs to detect supported number of
 virtqueues as well as a new command VIRTIO_NET_CTRL_RFS to program
 packet steering for unidirectional protocols.
[...]
 +Programming of the receive flow classificator is implicit.
 + Transmitting a packet of a specific flow on transmitqX will cause incoming
 + packets for this flow to be steered to receiveqX.
 + For uni-directional protocols, or where no packets have been transmitted
 + yet, device will steer a packet to a random queue out of the specified
 + receiveq0..receiveqn.
[...]

It doesn't seem like this is usable to implement accelerated RFS in the
guest, though perhaps that doesn't matter.  On the host side, presumably
you'll want vhost_net to do the equivalent of sock_rps_record_flow() -
only without a socket?  But in any case, that requires an rxhash, so I
don't see how this is supposed to work.

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

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


Re: [PATCH 1/3] virtio: change to_vp_device to an inlined definition

2012-12-05 Thread Stephen Hemminger
On Wed, 5 Dec 2012 15:03:27 +0800
Wanlong Gao gaowanl...@cn.fujitsu.com wrote:

 to_vp_device is worth changing to inlined definition.
 
 Signed-off-by: Wanlong Gao gaowanl...@cn.fujitsu.com
 ---
  drivers/virtio/virtio_pci.c | 6 +-
  1 file changed, 1 insertion(+), 5 deletions(-)
 
 diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
 index e3ecc94..7681fe3 100644
 --- a/drivers/virtio/virtio_pci.c
 +++ b/drivers/virtio/virtio_pci.c
 @@ -98,11 +98,7 @@ static struct pci_device_id virtio_pci_id_table[] = {
  
  MODULE_DEVICE_TABLE(pci, virtio_pci_id_table);
  
 -/* Convert a generic virtio device to our structure */
 -static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev)
 -{
 - return container_of(vdev, struct virtio_pci_device, vdev);
 -}
 +#define to_vp_device(_vdev) container_of(_vdev, struct virtio_pci_device, 
 vdev)

Just mark the function as inline. A macro loses type checking.


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


Re: [PATCH 1/3] virtio: change to_vp_device to an inlined definition

2012-12-05 Thread Rusty Russell
Wanlong Gao gaowanl...@cn.fujitsu.com writes:

 to_vp_device is worth changing to inlined definition.

Why?

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


Re: [PATCH 1/3] virtio: change to_vp_device to an inlined definition

2012-12-05 Thread Rusty Russell
Stephen Hemminger shemmin...@vyatta.com writes:

 On Wed, 5 Dec 2012 15:03:27 +0800
 Wanlong Gao gaowanl...@cn.fujitsu.com wrote:

 to_vp_device is worth changing to inlined definition.
 
 Signed-off-by: Wanlong Gao gaowanl...@cn.fujitsu.com
 ---
  drivers/virtio/virtio_pci.c | 6 +-
  1 file changed, 1 insertion(+), 5 deletions(-)
 
 diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
 index e3ecc94..7681fe3 100644
 --- a/drivers/virtio/virtio_pci.c
 +++ b/drivers/virtio/virtio_pci.c
 @@ -98,11 +98,7 @@ static struct pci_device_id virtio_pci_id_table[] = {
  
  MODULE_DEVICE_TABLE(pci, virtio_pci_id_table);
  
 -/* Convert a generic virtio device to our structure */
 -static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev)
 -{
 -return container_of(vdev, struct virtio_pci_device, vdev);
 -}
 +#define to_vp_device(_vdev) container_of(_vdev, struct virtio_pci_device, 
 vdev)

 Just mark the function as inline. A macro loses type checking.

No, don't.

Inline functions in C files are *wrong*: you lose the warning should it
ever become unused.  GCC's does a pretty good job these days: certainly
better than guessing.

(Yeah yeah, there are always exceptions.  I've used inline deliberately
to avoid a tangle of #ifdefs, and sometimes gcc really does screw up).

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


Re: [PATCH 1/3] virtio: change to_vp_device to an inlined definition

2012-12-05 Thread Wanlong Gao
On 12/06/2012 07:21 AM, Rusty Russell wrote:
 Wanlong Gao gaowanl...@cn.fujitsu.com writes:
 
 to_vp_device is worth changing to inlined definition.
 
 Why?

OK, I saw your comments, and I dropped this patch already.

Thanks,
Wanlong Gao

 
 Thanks,
 Rusty.
 

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