Linux virtualization list
 help / color / mirror / Atom feed
* Re: [RFC][ PATCH 1/3] vhost-net: support multiple buffer heads in receiver
From: David Stevens @ 2010-03-08  0:34 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: kvm, netdev, rusty, virtualization
In-Reply-To: <20100307153130.GA24997@redhat.com>

"Michael S. Tsirkin" <mst@redhat.com> wrote on 03/07/2010 07:31:30 AM:

> On Tue, Mar 02, 2010 at 05:20:15PM -0700, David Stevens wrote:
> > This patch generalizes buffer handling functions to
                                      NULL, NULL);
> > +               head.iov_base = (void *)vhost_get_vq_desc(&net->dev, 
vq,
> > +                       vq->iov, ARRAY_SIZE(vq->iov), &out, &in, NULL, 

> > NULL);
> 
> Should type for head be changed so that we do not need to cast?
> 
> I also prefer aligning descendants on the opening (.

        Yes, that's probably better; the indentation with the cast would
still wrap a lot, but I'll see what I can do here.


> >                 err = sock->ops->sendmsg(NULL, sock, &msg, len);
> >                 if (unlikely(err < 0)) {
> > -                       vhost_discard_vq_desc(vq);
> > +                       vhost_discard(vq, 1);
> 
> Isn't the original name a bit more descriptive?

        During development, I had both and I generally like
shorter names, but I can change it back.

> > +static int skb_head_len(struct sk_buff_head *skq)
> > +{
> > +       struct sk_buff *head;
> > +
> > +       head = skb_peek(skq);
> > +       if (head)
> > +               return head->len;
> > +       return 0;
> > +}
> > +
> 
> This is done without locking, which I think can crash
> if skb is consumed after we peek it but before we read the
> length.

        This thread is the only legitimate consumer, right? But
qemu has the file descriptor and I guess we shouldn't trust
that it won't give it to someone else; it'd break vhost, but
a crash would be inappropriate, of course. I'd like to avoid
the lock, but I have another idea here, so will investigate.

> 
> 
> >  /* Expects to be always run from workqueue - which acts as
> >   * read-size critical section for our kind of RCU. */
> >  static void handle_rx(struct vhost_net *net)
> >  {
> >         struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX];
> > -       unsigned head, out, in, log, s;
> > +       unsigned in, log, s;
> >         struct vhost_log *vq_log;
> >         struct msghdr msg = {
> >                 .msg_name = NULL,
> > @@ -204,10 +213,11 @@
> >         };
> > 
> >         size_t len, total_len = 0;
> > -       int err;
> > +       int err, headcount, datalen;
> >         size_t hdr_size;
> >         struct socket *sock = rcu_dereference(vq->private_data);
> > -       if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue))
> > +
> > +       if (!sock || !skb_head_len(&sock->sk->sk_receive_queue))
> >                 return;
> > 
> 
> Isn't this equivalent? Do you expect zero len skbs in socket?
> If yes, maybe we should discard these, not stop processing ...

        A zero return means "no skb's". They are equivalent; I
changed this call just to make it identical to the loop check,
but I don't have a strong attachment to this.


> >         vq_log = unlikely(vhost_has_feature(&net->dev, 
VHOST_F_LOG_ALL)) ?
> >                 vq->log : NULL;
> > 
> > -       for (;;) {
> > -               head = vhost_get_vq_desc(&net->dev, vq, vq->iov,
> > -                                        ARRAY_SIZE(vq->iov),
> > -                                        &out, &in,
> > -                                        vq_log, &log);
> > +       while ((datalen = skb_head_len(&sock->sk->sk_receive_queue))) 
{
> 
> This peeks in the queue to figure out how much data we have.
> It's a neat trick, but it does introduce new failure modes
> where an skb is consumed after we did the peek:
> - new skb could be shorter, we should return the unconsumed part
> - new skb could be longer, this will drop a packet.
>   maybe this last is not an issue as the race should be rare in practice

        As before, this loop is the only legitimate consumer of skb's; if
anyone else is reading the socket, it's broken. But since the file
descriptor is available to qemu, it's probably trusting qemu too much.
I don't believe there is a race at all on a working system; the head
can't change until we read it after this test, but I'll see if I can
come up with something better here. Closing the fd for qemu so vhost
has exclusive access might do it, but otherwise we could just get a
max-sized packet worth of buffers and then return them after the read.
That'd force us to wait with small packets when the ring is nearly
full, where we don't have to now, but I expect locking to read the head
length will hurt performance in all cases. Will try these ideas out.k

> 
> > +               headcount = vhost_get_heads(vq, datalen, &in, vq_log, 
> > &log);
> >                 /* OK, now we need to know about added descriptors. */
> > -               if (head == vq->num) {
> > +               if (!headcount) {
> >                         if (unlikely(vhost_enable_notify(vq))) {
> >                                 /* They have slipped one in as we were
> >                                  * doing that: check again. */
> > @@ -235,13 +242,6 @@
> >                          * they refilled. */
> >                         break;
> >                 }
> > -               /* We don't need to be notified again. */
> 
> you find this comment unhelpful?

        This code is changed in the later patches; the comment was
removed with that, but I got it in the wrong patch on the split.
I guess the comment is ok to stay, anyway, but notification may
require multiple buffers to be available; I had fixed that here, but
the final patch pushes that into the notify code, so yes, this can
go back in.

> > -               if (out) {
> > -                       vq_err(vq, "Unexpected descriptor format for 
RX: "
> > -                              "out %d, int %d\n",
> > -                              out, in);
> > -                       break;
> > -               }
> 
> 
> we still need this check, don't we?

        It's done in vhost_get_heads(); "out" isn't visible in handle_rx()
anymore.
 
> > +unsigned vhost_get_heads(struct vhost_virtqueue *vq, int datalen, int 

> > *iovcount,
> > +       struct vhost_log *log, unsigned int *log_num)
> 
> Could you please document this function's parameters? It's not obvious
> what iovcount, log, log_num are.

Yes. To answer the question, they are the same as vhost_get_vq_desc(),
except "iovcount" replaces "in" (and "out" is not needed in the caller).

> > +{
> > +       struct iovec *heads = vq->heads;
> > +       int out, in;
> > +       int hc = 0;
> > +
> > +       while (datalen > 0) {
> > +               if (hc >= VHOST_NET_MAX_SG) {
> > +                       vhost_discard(vq, hc);
> > +                       return 0;
> > +               }
> > +               heads[hc].iov_base = (void 
*)vhost_get_vq_desc(vq->dev, 
> > vq,
> > +                       vq->iov, ARRAY_SIZE(vq->iov), &out, &in, log, 
> > log_num);
> > +               if (heads[hc].iov_base == (void *)vq->num) {
> > +                       vhost_discard(vq, hc);
> > +                       return 0;
> > +               }
> > +               if (out || in <= 0) {
> > +                       vq_err(vq, "unexpected descriptor format for 
RX: "
> > +                               "out %d, in %d\n", out, in);
> > +                       vhost_discard(vq, hc);
> > +                       return 0;
> > +               }
> > +               heads[hc].iov_len = iov_length(vq->iov, in);
> > +               hc++;
> > +               datalen -= heads[hc].iov_len;
> > +       }
> > +       *iovcount = in;
> 
> 
> Only the last value?

        In this part of the split, it only goes through once; this is
changed to the accumulated value "seg" in a later patch. So, split
artifact.

  {
> >         struct vring_used_elem *used;
> > +       int i;
> > 
> > -       /* The virtqueue contains a ring of used buffers.  Get a 
pointer 
> > to the
> > -        * next entry in that used ring. */
> > -       used = &vq->used->ring[vq->last_used_idx % vq->num];
> > -       if (put_user(head, &used->id)) {
> > -               vq_err(vq, "Failed to write used id");
> > -               return -EFAULT;
> > -       }
> > -       if (put_user(len, &used->len)) {
> > -               vq_err(vq, "Failed to write used len");
> > -               return -EFAULT;
> > +       for (i=0; i<count; i++, vq->last_used_idx++) {
> 
> whitespace damage: I prefer space around =, <.
> I also use ++i, etc in this driver, better be consistent?
> Also for clarity, I prefer to put vq->last_used_idx inside the loop.

        OK.
> 
> > +               used = &vq->used->ring[vq->last_used_idx % vq->num];
> > +               if (put_user((unsigned)heads[i].iov_base, &used->id)) 
{
> > +                       vq_err(vq, "Failed to write used id");
> > +                       return -EFAULT;
> > +               }
> > +               if (put_user(heads[i].iov_len, &used->len)) {
> > +                       vq_err(vq, "Failed to write used len");
> > +                       return -EFAULT;
> > +               }
> 
> If this fails, last_used_idx will still be incremented, which I think is 
wrong.

        True, but if these fail, aren't we dead? I don't think we can 
recover
from an EFAULT in any of these; I didn't test those paths from the 
original,
but I think we need to bail out entirely for these cases, right?

 +-DLS


^ permalink raw reply

* Re: [RFC][ PATCH 3/3] vhost-net: Add mergeable RX buffer support to vhost-net
From: Michael S. Tsirkin @ 2010-03-07 16:26 UTC (permalink / raw)
  To: David Stevens; +Cc: rusty, netdev, kvm, virtualization
In-Reply-To: <OFD112C680.DB48ADA2-ON882576DB.0000CE4F-882576DB.0001E192@us.ibm.com>

On Tue, Mar 02, 2010 at 05:20:34PM -0700, David Stevens wrote:
> This patch glues them all together and makes sure we
> notify whenever we don't have enough buffers to receive
> a max-sized packet, and adds the feature bit.
> 
> Signed-off-by: David L Stevens <dlstevens@us.ibm.com>

Maybe split this up?

> diff -ruN net-next-p2/drivers/vhost/net.c net-next-p3/drivers/vhost/net.c
> --- net-next-p2/drivers/vhost/net.c     2010-03-02 13:01:34.000000000 
> -0800
> +++ net-next-p3/drivers/vhost/net.c     2010-03-02 15:25:15.000000000 
> -0800
> @@ -54,26 +54,6 @@
>         enum vhost_net_poll_state tx_poll_state;
>  };
>  
> -/* Pop first len bytes from iovec. Return number of segments used. */
> -static int move_iovec_hdr(struct iovec *from, struct iovec *to,
> -                         size_t len, int iov_count)
> -{
> -       int seg = 0;
> -       size_t size;
> -       while (len && seg < iov_count) {
> -               size = min(from->iov_len, len);
> -               to->iov_base = from->iov_base;
> -               to->iov_len = size;
> -               from->iov_len -= size;
> -               from->iov_base += size;
> -               len -= size;
> -               ++from;
> -               ++to;
> -               ++seg;
> -       }
> -       return seg;
> -}
> -
>  /* Caller must have TX VQ lock */
>  static void tx_poll_stop(struct vhost_net *net)
>  {
> @@ -97,7 +77,7 @@
>  static void handle_tx(struct vhost_net *net)
>  {
>         struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_TX];
> -       unsigned out, in, s;
> +       unsigned out, in;
>         struct iovec head;
>         struct msghdr msg = {
>                 .msg_name = NULL,
> @@ -110,6 +90,7 @@
>         size_t len, total_len = 0;
>         int err, wmem;
>         struct socket *sock = rcu_dereference(vq->private_data);
> +

I tend not to add empty lines if line below it is already short.

>         if (!sock)
>                 return;
>  
> @@ -166,11 +147,11 @@
>                 /* Skip header. TODO: support TSO. */
>                 msg.msg_iovlen = out;
>                 head.iov_len = len = iov_length(vq->iov, out);
> +

I tend not to add empty lines if line below it is a comment.

>                 /* Sanity check */
>                 if (!len) {
>                         vq_err(vq, "Unexpected header len for TX: "
> -                              "%zd expected %zd\n",
> -                              len, vq->guest_hlen);
> +                              "%zd expected %zd\n", len, vq->guest_hlen);
>                         break;
>                 }
>                 /* TODO: Check specific error and bomb out unless ENOBUFS? 
> */
> @@ -214,7 +195,7 @@
>  static void handle_rx(struct vhost_net *net)
>  {
>         struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX];
> -       unsigned in, log, s;
> +       unsigned in, log;
>         struct vhost_log *vq_log;
>         struct msghdr msg = {
>                 .msg_name = NULL,
> @@ -245,30 +226,36 @@
>                 if (!headcount) {
>                         vhost_enable_notify(vq);
>                         break;
> -               }
> +               } else if (vq->maxheadcount < headcount)
> +                       vq->maxheadcount = headcount;
>                 /* Skip header. TODO: support TSO/mergeable rx buffers. */
>                 msg.msg_iovlen = in;
>                 len = iov_length(vq->iov, in);
> -
>                 /* Sanity check */
>                 if (!len) {
>                         vq_err(vq, "Unexpected header len for RX: "
> -                              "%zd expected %zd\n",
> -                              len, vq->guest_hlen);
> +                              "%zd expected %zd\n", len, vq->guest_hlen);
>                         break;
>                 }
>                 err = sock->ops->recvmsg(NULL, sock, &msg,
>                                          len, MSG_DONTWAIT | MSG_TRUNC);
> -               /* TODO: Check specific error and bomb out unless EAGAIN? 
> */
>                 if (err < 0) {
> -                       vhost_discard(vq, 1);
> +                       vhost_discard(vq, headcount);
>                         break;
>                 }
>                 /* TODO: Should check and handle checksum. */
> +               if (vhost_has_feature(&net->dev, VIRTIO_NET_F_MRG_RXBUF)) 
> {
> +                       struct virtio_net_hdr_mrg_rxbuf *vhdr =
> +                               (struct virtio_net_hdr_mrg_rxbuf *)
> +                               vq->iov[0].iov_base;
> +                       /* add num_bufs */
> +                       vq->iov[0].iov_len = vq->guest_hlen;
> +                       vhdr->num_buffers = headcount;

I don't understand this. iov_base is a userspace pointer, isn't it.
How can you assign values to it like that?
Rusty also commented earlier that it's not a good idea to assume
specific layout, such as first chunk being large enough to
include virtio_net_hdr_mrg_rxbuf.

I think we need to use memcpy to/from iovec etc.

> +               }
>                 if (err > len) {
>                         pr_err("Discarded truncated rx packet: "
>                                " len %d > %zd\n", err, len);
> -                       vhost_discard(vq, 1);
> +                       vhost_discard(vq, headcount);
>                         continue;
>                 }
>                 len = err;
> @@ -573,8 +560,6 @@
>  
>  static int vhost_net_set_features(struct vhost_net *n, u64 features)
>  {
> -       size_t hdr_size = features & (1 << VHOST_NET_F_VIRTIO_NET_HDR) ?
> -               sizeof(struct virtio_net_hdr) : 0;
>         int i;
>         mutex_lock(&n->dev.mutex);
>         if ((features & (1 << VHOST_F_LOG_ALL)) &&
> diff -ruN net-next-p2/drivers/vhost/vhost.c 
> net-next-p3/drivers/vhost/vhost.c
> --- net-next-p2/drivers/vhost/vhost.c   2010-03-02 12:53:02.000000000 
> -0800
> +++ net-next-p3/drivers/vhost/vhost.c   2010-03-02 15:24:50.000000000 
> -0800
> @@ -115,6 +115,7 @@
>         vq->log_addr = -1ull;
>         vq->guest_hlen = 0;
>         vq->sock_hlen = 0;
> +       vq->maxheadcount = 0;
>         vq->private_data = NULL;
>         vq->log_base = NULL;
>         vq->error_ctx = NULL;
> @@ -410,6 +411,7 @@
>                 vq->last_avail_idx = s.num;
>                 /* Forget the cached index value. */
>                 vq->avail_idx = vq->last_avail_idx;
> +               vq->maxheadcount = 0;
>                 break;
>         case VHOST_GET_VRING_BASE:
>                 s.index = idx;
> @@ -1114,10 +1116,23 @@
>         return 0;
>  }
>  
> +int vhost_available(struct vhost_virtqueue *vq)
> +{
> +       int avail;
> +
> +       if (!vq->maxheadcount)  /* haven't got any yet */
> +               return 1;
> +       avail = vq->avail_idx - vq->last_avail_idx;
> +       if (avail < 0)
> +               avail += 0x10000; /* wrapped */
> +       return avail;
> +}
> +
>  /* This actually signals the guest, using eventfd. */
>  void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq)
>  {
>         __u16 flags = 0;
> +

I tend not to add empty lines if a line above it is already short.

>         if (get_user(flags, &vq->avail->flags)) {
>                 vq_err(vq, "Failed to get flags");
>                 return;
> @@ -1125,7 +1140,7 @@
>  
>         /* If they don't want an interrupt, don't signal, unless empty. */
>         if ((flags & VRING_AVAIL_F_NO_INTERRUPT) &&
> -           (vq->avail_idx != vq->last_avail_idx ||
> +           (vhost_available(vq) > vq->maxheadcount ||

I don't understand this change. It seems to make
code not match the comments.

>              !vhost_has_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY)))
>                 return;
>  
> diff -ruN net-next-p2/drivers/vhost/vhost.h 
> net-next-p3/drivers/vhost/vhost.h
> --- net-next-p2/drivers/vhost/vhost.h   2010-03-02 13:02:03.000000000 
> -0800
> +++ net-next-p3/drivers/vhost/vhost.h   2010-03-02 14:29:44.000000000 
> -0800
> @@ -85,6 +85,7 @@
>         struct iovec iov[VHOST_NET_MAX_SG+1]; /* an extra for vnet hdr */
>         struct iovec heads[VHOST_NET_MAX_SG];
>         size_t guest_hlen, sock_hlen;
> +       int maxheadcount;

I don't completely understand what does this field does.
It seems to be only set on rx? Maybe name should reflect this?

>         /* We use a kind of RCU to access private pointer.
>          * All readers access it from workqueue, which makes it possible 
> to
>          * flush the workqueue instead of synchronize_rcu. Therefore 
> readers do
> @@ -151,7 +152,8 @@
>         VHOST_FEATURES = (1 << VIRTIO_F_NOTIFY_ON_EMPTY) |
>                          (1 << VIRTIO_RING_F_INDIRECT_DESC) |
>                          (1 << VHOST_F_LOG_ALL) |
> -                        (1 << VHOST_NET_F_VIRTIO_NET_HDR),
> +                        (1 << VHOST_NET_F_VIRTIO_NET_HDR) |
> +                        (1 << VIRTIO_NET_F_MRG_RXBUF),
>  };
>  
>  static inline int vhost_has_feature(struct vhost_dev *dev, int bit)
> 



^ permalink raw reply

* Re: [RFC][ PATCH 2/3] vhost-net: handle vnet_hdr processing for MRG_RX_BUF
From: Michael S. Tsirkin @ 2010-03-07 16:12 UTC (permalink / raw)
  To: David Stevens; +Cc: rusty, netdev, kvm, virtualization
In-Reply-To: <OF9CBCD776.645508E4-ON882576DB.0000CB6E-882576DB.0001DED1@us.ibm.com>

On Tue, Mar 02, 2010 at 05:20:26PM -0700, David Stevens wrote:
> This patch adds vnet_hdr processing for mergeable buffer
> support to vhost-net.
> 
> Signed-off-by: David L Stevens <dlstevens@us.ibm.com>
> 
> diff -ruN net-next-p1/drivers/vhost/net.c net-next-p2/drivers/vhost/net.c

Could you please add -p to diff flags so that it's easier
to figure out which function is changes?

> --- net-next-p1/drivers/vhost/net.c     2010-03-01 11:44:22.000000000 
> -0800
> +++ net-next-p2/drivers/vhost/net.c     2010-03-02 13:01:34.000000000 
> -0800
> @@ -109,7 +109,6 @@
>         };
>         size_t len, total_len = 0;
>         int err, wmem;
> -       size_t hdr_size;
>         struct socket *sock = rcu_dereference(vq->private_data);
>         if (!sock)
>                 return;
> @@ -124,7 +123,6 @@
>  
>         if (wmem < sock->sk->sk_sndbuf * 2)
>                 tx_poll_stop(net);
> -       hdr_size = vq->hdr_size;
>  
>         for (;;) {
>                 head.iov_base = (void *)vhost_get_vq_desc(&net->dev, vq,
> @@ -148,25 +146,45 @@
>                                "out %d, int %d\n", out, in);
>                         break;
>                 }
> +               if (vq->guest_hlen > vq->sock_hlen) {
> +                       if (msg.msg_iov[0].iov_len == vq->guest_hlen)
> +                               msg.msg_iov[0].iov_len = vq->sock_hlen;
> +                       else if (out == ARRAY_SIZE(vq->iov))
> +                               vq_err(vq, "handle_tx iov overflow!");
> +                       else {
> +                               int i;
> +
> +                               /* give header its own iov */
> +                               for (i=out; i>0; ++i)
> +                                       msg.msg_iov[i+1] = msg.msg_iov[i];
> +                               msg.msg_iov[0].iov_len = vq->sock_hlen;
> +                               msg.msg_iov[1].iov_base += vq->guest_hlen;
> +                               msg.msg_iov[1].iov_len -= vq->guest_hlen;
> +                               out++;

We seem to spend a fair bit of code here and elsewhere trying to cover
the diff between header size in guest and host.  In hindsight, it was
not a good idea to put new padding between data and the header:
virtio-net should have added it *before*. But it is what it is.

Wouldn't it be easier to just add an ioctl to tap so that
vnet header size is made bigger by 4 bytes?

> +                       }
> +               }
>                 /* Skip header. TODO: support TSO. */
> -               s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, out);
>                 msg.msg_iovlen = out;
>                 head.iov_len = len = iov_length(vq->iov, out);
>                 /* Sanity check */
>                 if (!len) {
>                         vq_err(vq, "Unexpected header len for TX: "
>                                "%zd expected %zd\n",
> -                              iov_length(vq->hdr, s), hdr_size);
> +                              len, vq->guest_hlen);
>                         break;
>                 }
>                 /* TODO: Check specific error and bomb out unless ENOBUFS? 
> */
>                 err = sock->ops->sendmsg(NULL, sock, &msg, len);
>                 if (unlikely(err < 0)) {
> -                       vhost_discard(vq, 1);
> -                       tx_poll_start(net, sock);
> +                       if (err == -EAGAIN) {

The comment mentions ENOBUFS. Are you sure it's EAGAIN?

> +                               tx_poll_start(net, sock);

Don't we need to call discard to move the last avail header back?

> +                       } else {
> +                               vq_err(vq, "sendmsg: errno %d\n", -err);
> +                               /* drop packet; do not discard/resend */
> + vhost_add_used_and_signal(&net->dev,vq,&head,1);
> +                       }
>                         break;
> -               }
> -               if (err != len)
> +               } else if (err != len)


Previous if ends with break so no need for else here.

>                         pr_err("Truncated TX packet: "
>                                " len %d != %zd\n", err, len);
>                 vhost_add_used_and_signal(&net->dev, vq, &head, 1);
> @@ -207,14 +225,8 @@
>                 .msg_flags = MSG_DONTWAIT,
>         };
>  
> -       struct virtio_net_hdr hdr = {
> -               .flags = 0,
> -               .gso_type = VIRTIO_NET_HDR_GSO_NONE
> -       };
> -
>         size_t len, total_len = 0;
>         int err, headcount, datalen;
> -       size_t hdr_size;
>         struct socket *sock = rcu_dereference(vq->private_data);
>  
>         if (!sock || !skb_head_len(&sock->sk->sk_receive_queue))
> @@ -223,7 +235,6 @@
>         use_mm(net->dev.mm);
>         mutex_lock(&vq->mutex);
>         vhost_disable_notify(vq);
> -       hdr_size = vq->hdr_size;
>  
>         vq_log = unlikely(vhost_has_feature(&net->dev, VHOST_F_LOG_ALL)) ?
>                 vq->log : NULL;
> @@ -232,25 +243,18 @@
>                 headcount = vhost_get_heads(vq, datalen, &in, vq_log, 
> &log);
>                 /* OK, now we need to know about added descriptors. */
>                 if (!headcount) {
> -                       if (unlikely(vhost_enable_notify(vq))) {
> -                               /* They have slipped one in as we were
> -                                * doing that: check again. */
> -                               vhost_disable_notify(vq);
> -                               continue;
> -                       }
> -                       /* Nothing new?  Wait for eventfd to tell us
> -                        * they refilled. */
> +                       vhost_enable_notify(vq);


You don't think this race can happen?

>                         break;
>                 }
>                 /* Skip header. TODO: support TSO/mergeable rx buffers. */
> -               s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, in);
>                 msg.msg_iovlen = in;
>                 len = iov_length(vq->iov, in);
> +
>                 /* Sanity check */
>                 if (!len) {
>                         vq_err(vq, "Unexpected header len for RX: "
>                                "%zd expected %zd\n",
> -                              iov_length(vq->hdr, s), hdr_size);
> +                              len, vq->guest_hlen);
>                         break;
>                 }
>                 err = sock->ops->recvmsg(NULL, sock, &msg,
> @@ -268,13 +272,7 @@
>                         continue;
>                 }
>                 len = err;
> -               err = memcpy_toiovec(vq->hdr, (unsigned char *)&hdr, 
> hdr_size);
> -               if (err) {
> -                       vq_err(vq, "Unable to write vnet_hdr at addr %p: 
> %d\n",
> -                              vq->iov->iov_base, err);
> -                       break;
> -               }
> -               len += hdr_size;
> +               len += vq->guest_hlen - vq->sock_hlen;
>                 vhost_add_used_and_signal(&net->dev, vq, vq->heads, 
> headcount);
>                 if (unlikely(vq_log))
>                         vhost_log_write(vq, vq_log, log, len);
> @@ -483,6 +481,13 @@
>         return ERR_PTR(-ENOTSOCK);
>  }
>  
> +static int vhost_sock_is_raw(struct socket *sock)
> +{
> +       if (!sock || !sock->sk)
> +               return 0;
> +       return sock->sk->sk_type == SOCK_RAW;
> +}
> +
>  static long vhost_net_set_backend(struct vhost_net *n, unsigned index, 
> int fd)
>  {
>         struct socket *sock, *oldsock;
> @@ -519,6 +524,20 @@
>  
>         vhost_net_disable_vq(n, vq);
>         rcu_assign_pointer(vq->private_data, sock);
> +
> +       if (sock && sock->sk) {
> +               if (!vhost_sock_is_raw(sock) ||

I dislike this backend-specific code, it ties us with specifics of
backend implementations, which change without notice.  Ideally all
backend-specific stuff should live in userspace, userspace programs
vhost device appropriately.

> +                   vhost_has_feature(&n->dev, 
> VHOST_NET_F_VIRTIO_NET_HDR)) {
> +                       vq->sock_hlen = sizeof(struct virtio_net_hdr);
> +                       if (vhost_has_feature(&n->dev, 
> VIRTIO_NET_F_MRG_RXBUF))
> +                               vq->guest_hlen =
> +                                       sizeof(struct 
> virtio_net_hdr_mrg_rxbuf);
> +                       else
> +                               vq->guest_hlen = sizeof(struct 
> virtio_net_hdr);
> +               } else
> +                       vq->guest_hlen = vq->sock_hlen = 0;
> +       } else
> +               vq_err(vq, "vhost_net_set_backend: sock->sk is NULL");

As proposed above, IMO it would be nicer to add an ioctl in tap
that let us program header size.

>         vhost_net_enable_vq(n, vq);
>         mutex_unlock(&vq->mutex);
>  done:
> @@ -566,8 +585,17 @@
>         n->dev.acked_features = features;
>         smp_wmb();
>         for (i = 0; i < VHOST_NET_VQ_MAX; ++i) {
> -               mutex_lock(&n->vqs[i].mutex);
> -               n->vqs[i].hdr_size = hdr_size;
> +               struct vhost_virtqueue *vq = n->vqs + i;
> +               struct socket *sock = vq->private_data;
> +
> +               mutex_lock(&vq->mutex);
> +               if (features & (1 << VIRTIO_NET_F_MRG_RXBUF))
> +                       vq->sock_hlen = sizeof(struct 
> virtio_net_hdr_mrg_rxbuf);
> +               else if (features & (1 << VHOST_NET_F_VIRTIO_NET_HDR) ||
> +                        !vhost_sock_is_raw(sock))
> +                       vq->sock_hlen = sizeof(struct virtio_net_hdr);
> +               else
> +                       vq->sock_hlen = 0;
>                 mutex_unlock(&n->vqs[i].mutex);
>         }
>         vhost_net_flush(n);
> diff -ruN net-next-p1/drivers/vhost/vhost.c 
> net-next-p2/drivers/vhost/vhost.c
> --- net-next-p1/drivers/vhost/vhost.c   2010-03-01 11:44:06.000000000 
> -0800
> +++ net-next-p2/drivers/vhost/vhost.c   2010-03-02 12:53:02.000000000 
> -0800
> @@ -113,7 +113,8 @@
>         vq->used_flags = 0;
>         vq->log_used = false;
>         vq->log_addr = -1ull;
> -       vq->hdr_size = 0;
> +       vq->guest_hlen = 0;
> +       vq->sock_hlen = 0;
>         vq->private_data = NULL;
>         vq->log_base = NULL;
>         vq->error_ctx = NULL;
> @@ -848,20 +849,85 @@
>         return 0;
>  }
>  
> +static int
> +vhost_get_hdr(struct vhost_virtqueue *vq, int *in, struct vhost_log *log,
> +       int *log_num)
> +{
> +       struct iovec *heads = vq->heads;
> +       struct iovec *iov = vq->iov;
> +       int out;
> +
> +       *in = 0;
> +       iov[0].iov_len = 0;
> +
> +       /* get buffer, starting from iov[1] */
> +       heads[0].iov_base = (void *)vhost_get_vq_desc(vq->dev, vq,
> +               vq->iov+1, ARRAY_SIZE(vq->iov)-1, &out, in, log, log_num);
> +       if (out || *in <= 0) {
> +               vq_err(vq, "unexpected descriptor format for RX: out %d, "
> +                       "in %d\n", out, *in);
> +               return 0;
> +       }
> +       if (heads[0].iov_base == (void *)vq->num)
> +               return 0;
> +
> +       /* make iov[0] the header */
> +       if (!vq->guest_hlen) {
> +               if (vq->sock_hlen) {
> +                       static struct virtio_net_hdr junk; /* bit bucket 
> */
> +
> +                       iov[0].iov_base = &junk;
> +                       iov[0].iov_len = sizeof(junk);
> +               } else
> +                       iov[0].iov_len = 0;
> +       }
> +       if (vq->sock_hlen < vq->guest_hlen) {
> +               iov[0].iov_base = iov[1].iov_base;
> +               iov[0].iov_len = vq->sock_hlen;
> +
> +               if (iov[1].iov_len < vq->sock_hlen) {
> +                       vq_err(vq, "can't fit header in one buffer!");
> +                       vhost_discard(vq, 1);
> +                       return 0;
> +               }
> +               if (!vq->sock_hlen) {
> +                       static const struct virtio_net_hdr_mrg_rxbuf hdr = 
> {
> +                               .hdr.flags = 0,
> +                               .hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE
> +                       };
> +                       memcpy(iov[0].iov_base, &hdr, vq->guest_hlen);
> +               }
> +               iov[1].iov_base += vq->guest_hlen;
> +               iov[1].iov_len -= vq->guest_hlen;
> +       }
> +       return 1;

The above looks kind of scary, lots of special-casing.  I'll send a
patch for tap to set vnet header size, let's see if it makes life easier
for us.

> +}
> +
>  unsigned vhost_get_heads(struct vhost_virtqueue *vq, int datalen, int 
> *iovcount,
>         struct vhost_log *log, unsigned int *log_num)
>  {
>         struct iovec *heads = vq->heads;
> -       int out, in;
> +       int out, in = 0;
> +       int seg = 0;
>         int hc = 0;

I think it's better to stick to simple names like i
for index variables, alternatively give it a meaningful
name like "count".

>  
> +       if (vq->guest_hlen != vq->sock_hlen) {

Sticking guest_hlen/sock_hlen in vhost is somewhat ugly.

> +               seg = vhost_get_hdr(vq, &in, log, log_num);
> +               if (!seg)
> +                       return 0;
> +               hc++;
> +               datalen -= iov_length(vq->iov+seg, in);
> +               seg += in;
> +       }
> +
>         while (datalen > 0) {
>                 if (hc >= VHOST_NET_MAX_SG) {
>                         vhost_discard(vq, hc);
>                         return 0;
>                 }
>                 heads[hc].iov_base = (void *)vhost_get_vq_desc(vq->dev, 
> vq,
> -                       vq->iov, ARRAY_SIZE(vq->iov), &out, &in, log, 
> log_num);
> +                       vq->iov+seg, ARRAY_SIZE(vq->iov)-seg, &out, &in,
> +                       log, log_num);
>                 if (heads[hc].iov_base == (void *)vq->num) {
>                         vhost_discard(vq, hc);
>                         return 0;
> @@ -872,11 +938,12 @@
>                         vhost_discard(vq, hc);
>                         return 0;
>                 }
> -               heads[hc].iov_len = iov_length(vq->iov, in);
> -               hc++;
> +               heads[hc].iov_len = iov_length(vq->iov+seg, in);
>                 datalen -= heads[hc].iov_len;
> +               hc++;
> +               seg += in;
>         }
> -       *iovcount = in;
> +       *iovcount = seg;
>         return hc;
>  }
>  
> diff -ruN net-next-p1/drivers/vhost/vhost.h 
> net-next-p2/drivers/vhost/vhost.h
> --- net-next-p1/drivers/vhost/vhost.h   2010-03-01 11:42:18.000000000 
> -0800
> +++ net-next-p2/drivers/vhost/vhost.h   2010-03-02 13:02:03.000000000 
> -0800
> @@ -82,10 +82,9 @@
>         u64 log_addr;
>  
>         struct iovec indirect[VHOST_NET_MAX_SG];
> -       struct iovec iov[VHOST_NET_MAX_SG];
> -       struct iovec hdr[VHOST_NET_MAX_SG];
> +       struct iovec iov[VHOST_NET_MAX_SG+1]; /* an extra for vnet hdr */
>         struct iovec heads[VHOST_NET_MAX_SG];
> -       size_t hdr_size;
> +       size_t guest_hlen, sock_hlen;
>         /* We use a kind of RCU to access private pointer.
>          * All readers access it from workqueue, which makes it possible 
> to
>          * flush the workqueue instead of synchronize_rcu. Therefore 
> readers do
> 



^ permalink raw reply

* Re: [RFC][ PATCH 1/3] vhost-net: support multiple buffer heads in receiver
From: Michael S. Tsirkin @ 2010-03-07 15:31 UTC (permalink / raw)
  To: David Stevens; +Cc: rusty, netdev, kvm, virtualization
In-Reply-To: <OF201C1B9E.C89ADF9F-ON882576DB.00006AD7-882576DB.0001DA4E@us.ibm.com>

On Tue, Mar 02, 2010 at 05:20:15PM -0700, David Stevens wrote:
> This patch generalizes buffer handling functions to
> support multiple buffer heads.
> 
> In-line for viewing, attached for applying.
> Signed-off-by: David L Stevens <dlstevens@us.ibm.com>
> diff -ruN net-next-p0/drivers/vhost/net.c net-next-p1/drivers/vhost/net.c
> --- net-next-p0/drivers/vhost/net.c     2010-02-24 12:59:24.000000000 
> -0800
> +++ net-next-p1/drivers/vhost/net.c     2010-03-01 11:44:22.000000000 
> -0800
> @@ -97,7 +97,8 @@
>  static void handle_tx(struct vhost_net *net)
>  {
>         struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_TX];
> -       unsigned head, out, in, s;
> +       unsigned out, in, s;
> +       struct iovec head;
>         struct msghdr msg = {
>                 .msg_name = NULL,
>                 .msg_namelen = 0,
> @@ -126,12 +127,10 @@
>         hdr_size = vq->hdr_size;
>  
>         for (;;) {
> -               head = vhost_get_vq_desc(&net->dev, vq, vq->iov,
> -                                        ARRAY_SIZE(vq->iov),
> -                                        &out, &in,
> -                                        NULL, NULL);
> +               head.iov_base = (void *)vhost_get_vq_desc(&net->dev, vq,
> +                       vq->iov, ARRAY_SIZE(vq->iov), &out, &in, NULL, 
> NULL);

Should type for head be changed so that we do not need to cast?

I also prefer aligning descendants on the opening (.

>                 /* Nothing new?  Wait for eventfd to tell us they 
> refilled. */
> -               if (head == vq->num) {
> +               if (head.iov_base == (void *)vq->num) {
>                         wmem = atomic_read(&sock->sk->sk_wmem_alloc);
>                         if (wmem >= sock->sk->sk_sndbuf * 3 / 4) {
>                                 tx_poll_start(net, sock);
> @@ -152,7 +151,7 @@
>                 /* Skip header. TODO: support TSO. */
>                 s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, out);
>                 msg.msg_iovlen = out;
> -               len = iov_length(vq->iov, out);
> +               head.iov_len = len = iov_length(vq->iov, out);
>                 /* Sanity check */
>                 if (!len) {
>                         vq_err(vq, "Unexpected header len for TX: "
> @@ -163,14 +162,14 @@
>                 /* TODO: Check specific error and bomb out unless ENOBUFS? 
> */
>                 err = sock->ops->sendmsg(NULL, sock, &msg, len);
>                 if (unlikely(err < 0)) {
> -                       vhost_discard_vq_desc(vq);
> +                       vhost_discard(vq, 1);

Isn't the original name a bit more descriptive?

>                         tx_poll_start(net, sock);
>                         break;
>                 }
>                 if (err != len)
>                         pr_err("Truncated TX packet: "
>                                " len %d != %zd\n", err, len);
> -               vhost_add_used_and_signal(&net->dev, vq, head, 0);
> +               vhost_add_used_and_signal(&net->dev, vq, &head, 1);
>                 total_len += len;
>                 if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
>                         vhost_poll_queue(&vq->poll);
> @@ -182,12 +181,22 @@
>         unuse_mm(net->dev.mm);
>  }
>  
> +static int skb_head_len(struct sk_buff_head *skq)
> +{
> +       struct sk_buff *head;
> +
> +       head = skb_peek(skq);
> +       if (head)
> +               return head->len;
> +       return 0;
> +}
> +

This is done without locking, which I think can crash
if skb is consumed after we peek it but before we read the
length.


>  /* Expects to be always run from workqueue - which acts as
>   * read-size critical section for our kind of RCU. */
>  static void handle_rx(struct vhost_net *net)
>  {
>         struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX];
> -       unsigned head, out, in, log, s;
> +       unsigned in, log, s;
>         struct vhost_log *vq_log;
>         struct msghdr msg = {
>                 .msg_name = NULL,
> @@ -204,10 +213,11 @@
>         };
>  
>         size_t len, total_len = 0;
> -       int err;
> +       int err, headcount, datalen;
>         size_t hdr_size;
>         struct socket *sock = rcu_dereference(vq->private_data);
> -       if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue))
> +
> +       if (!sock || !skb_head_len(&sock->sk->sk_receive_queue))
>                 return;
>  

Isn't this equivalent? Do you expect zero len skbs in socket?
If yes, maybe we should discard these, not stop processing ...


>         use_mm(net->dev.mm);
> @@ -218,13 +228,10 @@
>         vq_log = unlikely(vhost_has_feature(&net->dev, VHOST_F_LOG_ALL)) ?
>                 vq->log : NULL;
>  
> -       for (;;) {
> -               head = vhost_get_vq_desc(&net->dev, vq, vq->iov,
> -                                        ARRAY_SIZE(vq->iov),
> -                                        &out, &in,
> -                                        vq_log, &log);
> +       while ((datalen = skb_head_len(&sock->sk->sk_receive_queue))) {

This peeks in the queue to figure out how much data we have.
It's a neat trick, but it does introduce new failure modes
where an skb is consumed after we did the peek:
- new skb could be shorter, we should return the unconsumed part
- new skb could be longer, this will drop a packet.
  maybe this last is not an issue as the race should be rare in practice

> +               headcount = vhost_get_heads(vq, datalen, &in, vq_log, 
> &log);
>                 /* OK, now we need to know about added descriptors. */
> -               if (head == vq->num) {
> +               if (!headcount) {
>                         if (unlikely(vhost_enable_notify(vq))) {
>                                 /* They have slipped one in as we were
>                                  * doing that: check again. */
> @@ -235,13 +242,6 @@
>                          * they refilled. */
>                         break;
>                 }
> -               /* We don't need to be notified again. */

you find this comment unhelpful?

> -               if (out) {
> -                       vq_err(vq, "Unexpected descriptor format for RX: "
> -                              "out %d, int %d\n",
> -                              out, in);
> -                       break;
> -               }


we still need this check, don't we?

>                 /* Skip header. TODO: support TSO/mergeable rx buffers. */
>                 s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, in);
>                 msg.msg_iovlen = in;
> @@ -257,14 +257,14 @@
>                                          len, MSG_DONTWAIT | MSG_TRUNC);
>                 /* TODO: Check specific error and bomb out unless EAGAIN? 
> */
>                 if (err < 0) {
> -                       vhost_discard_vq_desc(vq);
> +                       vhost_discard(vq, 1);
>                         break;
>                 }
>                 /* TODO: Should check and handle checksum. */
>                 if (err > len) {
>                         pr_err("Discarded truncated rx packet: "
>                                " len %d > %zd\n", err, len);
> -                       vhost_discard_vq_desc(vq);
> +                       vhost_discard(vq, 1);
>                         continue;
>                 }
>                 len = err;
> @@ -275,7 +275,7 @@
>                         break;
>                 }
>                 len += hdr_size;
> -               vhost_add_used_and_signal(&net->dev, vq, head, len);
> +               vhost_add_used_and_signal(&net->dev, vq, vq->heads, 
> headcount);
>                 if (unlikely(vq_log))
>                         vhost_log_write(vq, vq_log, log, len);
>                 total_len += len;
> diff -ruN net-next-p0/drivers/vhost/vhost.c 
> net-next-p1/drivers/vhost/vhost.c
> --- net-next-p0/drivers/vhost/vhost.c   2010-02-15 20:08:35.000000000 
> -0800
> +++ net-next-p1/drivers/vhost/vhost.c   2010-03-01 11:44:06.000000000 
> -0800
> @@ -848,6 +848,38 @@
>         return 0;
>  }
>  
> +unsigned vhost_get_heads(struct vhost_virtqueue *vq, int datalen, int 
> *iovcount,
> +       struct vhost_log *log, unsigned int *log_num)

Could you please document this function's parameters? It's not obvious
what iovcount, log, log_num are.

> +{
> +       struct iovec *heads = vq->heads;
> +       int out, in;
> +       int hc = 0;
> +
> +       while (datalen > 0) {
> +               if (hc >= VHOST_NET_MAX_SG) {
> +                       vhost_discard(vq, hc);
> +                       return 0;
> +               }
> +               heads[hc].iov_base = (void *)vhost_get_vq_desc(vq->dev, 
> vq,
> +                       vq->iov, ARRAY_SIZE(vq->iov), &out, &in, log, 
> log_num);
> +               if (heads[hc].iov_base == (void *)vq->num) {
> +                       vhost_discard(vq, hc);
> +                       return 0;
> +               }
> +               if (out || in <= 0) {
> +                       vq_err(vq, "unexpected descriptor format for RX: "
> +                               "out %d, in %d\n", out, in);
> +                       vhost_discard(vq, hc);
> +                       return 0;
> +               }
> +               heads[hc].iov_len = iov_length(vq->iov, in);
> +               hc++;
> +               datalen -= heads[hc].iov_len;
> +       }
> +       *iovcount = in;


Only the last value?

> +       return hc;
> +}
> +
>  /* 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
> @@ -973,31 +1005,32 @@
>  }
>  
>  /* Reverse the effect of vhost_get_vq_desc. Useful for error handling. */
> -void vhost_discard_vq_desc(struct vhost_virtqueue *vq)
> +void vhost_discard(struct vhost_virtqueue *vq, int n)
>  {
> -       vq->last_avail_idx--;
> +       vq->last_avail_idx -= n;
>  }
>  
>  /* After we've used one of their buffers, we tell them about it.  We'll 
> then
>   * want to notify the guest, using eventfd. */
> -int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int 
> len)
> +int vhost_add_used(struct vhost_virtqueue *vq, struct iovec *heads, int 
> count)
>  {
>         struct vring_used_elem *used;
> +       int i;
>  
> -       /* The virtqueue contains a ring of used buffers.  Get a pointer 
> to the
> -        * next entry in that used ring. */
> -       used = &vq->used->ring[vq->last_used_idx % vq->num];
> -       if (put_user(head, &used->id)) {
> -               vq_err(vq, "Failed to write used id");
> -               return -EFAULT;
> -       }
> -       if (put_user(len, &used->len)) {
> -               vq_err(vq, "Failed to write used len");
> -               return -EFAULT;
> +       for (i=0; i<count; i++, vq->last_used_idx++) {

whitespace damage: I prefer space around =, <.
I also use ++i, etc in this driver, better be consistent?
Also for clarity, I prefer to put vq->last_used_idx inside the loop.

> +               used = &vq->used->ring[vq->last_used_idx % vq->num];
> +               if (put_user((unsigned)heads[i].iov_base, &used->id)) {
> +                       vq_err(vq, "Failed to write used id");
> +                       return -EFAULT;
> +               }
> +               if (put_user(heads[i].iov_len, &used->len)) {
> +                       vq_err(vq, "Failed to write used len");
> +                       return -EFAULT;
> +               }

If this fails, last_used_idx will still be incremented, which I think is wrong.

>         }
>         /* Make sure buffer is written before we update index. */
>         smp_wmb();
> -       if (put_user(vq->last_used_idx + 1, &vq->used->idx)) {
> +       if (put_user(vq->last_used_idx, &vq->used->idx)) {

here, too

>                 vq_err(vq, "Failed to increment used idx");
>                 return -EFAULT;
>         }
> @@ -1011,7 +1044,6 @@
>                 if (vq->log_ctx)
>                         eventfd_signal(vq->log_ctx, 1);
>         }
> -       vq->last_used_idx++;
>         return 0;
>  }
>  
> @@ -1038,9 +1070,9 @@
>  /* And here's the combo meal deal.  Supersize me! */
>  void vhost_add_used_and_signal(struct vhost_dev *dev,
>                                struct vhost_virtqueue *vq,
> -                              unsigned int head, int len)
> +                              struct iovec *heads, int count)
>  {
> -       vhost_add_used(vq, head, len);
> +       vhost_add_used(vq, heads, count);
>         vhost_signal(dev, vq);
>  }
>  
> diff -ruN net-next-p0/drivers/vhost/vhost.h 
> net-next-p1/drivers/vhost/vhost.h
> --- net-next-p0/drivers/vhost/vhost.h   2010-02-15 20:08:35.000000000 
> -0800
> +++ net-next-p1/drivers/vhost/vhost.h   2010-03-01 11:42:18.000000000 
> -0800
> @@ -84,6 +84,7 @@
>         struct iovec indirect[VHOST_NET_MAX_SG];
>         struct iovec iov[VHOST_NET_MAX_SG];
>         struct iovec hdr[VHOST_NET_MAX_SG];
> +       struct iovec heads[VHOST_NET_MAX_SG];
>         size_t hdr_size;
>         /* We use a kind of RCU to access private pointer.
>          * All readers access it from workqueue, which makes it possible 
> to
> @@ -120,16 +121,18 @@
>  int vhost_vq_access_ok(struct vhost_virtqueue *vq);
>  int vhost_log_access_ok(struct vhost_dev *);
>  
> +unsigned vhost_get_heads(struct vhost_virtqueue *, int datalen, int 
> *iovcount,
> +                       struct vhost_log *log, unsigned int *log_num);
>  unsigned vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *,
>                            struct iovec iov[], unsigned int iov_count,
>                            unsigned int *out_num, unsigned int *in_num,
>                            struct vhost_log *log, unsigned int *log_num);
> -void vhost_discard_vq_desc(struct vhost_virtqueue *);
> +void vhost_discard(struct vhost_virtqueue *, int);
>  
> -int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len);
> -void vhost_signal(struct vhost_dev *, struct vhost_virtqueue *);
> +int vhost_add_used(struct vhost_virtqueue *, struct iovec *heads, int 
> count);
>  void vhost_add_used_and_signal(struct vhost_dev *, struct vhost_virtqueue 
> *,
> -                              unsigned int head, int len);
> +                              struct iovec *heads, int count);
> +void vhost_signal(struct vhost_dev *, struct vhost_virtqueue *);
>  void vhost_disable_notify(struct vhost_virtqueue *);
>  bool vhost_enable_notify(struct vhost_virtqueue *);
>  



^ permalink raw reply

* Re: [PULL] virtio
From: Alexander Graf @ 2010-03-07 11:11 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Shirley Ma, Jamie Lokier, linux-kernel, virtualization,
	Anthony Liguori, Amit Shah, Linus Torvalds, hch
In-Reply-To: <20100307110457.GB20004@redhat.com>


On 07.03.2010, at 12:04, Michael S. Tsirkin wrote:

> On Sun, Mar 07, 2010 at 11:57:23AM +0100, Alexander Graf wrote:
>> 
>> On 07.03.2010, at 11:42, Michael S. Tsirkin wrote:
>> 
>>> Linus,
>>> Please pull another virtio fix: this one fixes hotplug and
>>> was supposed to be applied by Rusty already
>>> (http://lkml.org/lkml/2009/11/30/451), but apparently got lost,
>>> somehow.
>>> 
>>> Thanks!
>>> 
>>> The following changes since commit 3119815912a220bdac943dfbdfee640414c0c611:
>>> Michael S. Tsirkin (1):
>>>       virtio: fix out of range array access
>>> 
>>> are available in the git repository at:
>>> 
>>> git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git for-linus
>>> 
>>> Michael S. Tsirkin (1):
>>>     virtio: set pci bus master enable bit
>> 
>> This is still missing an identifier for the hypervisor. We need to know if the guest will ever set bus master enabled or not, so we can have a compat hack in qemu to not check for it.
>> 
>> 
>> Alex
> 
> This patch fixes hotplug with qemu 0.11-0.12 which can't make use of a new
> identifier without a time machine.

For 0.12 there's -stable and I don't think the bad patch is in 0.11 yet?

> IMHO we can't add new identifiers in time for 2.6.34 anyway, so if you
> want to do that, please send a patch and have it queued up for the next
> release. But I don't think we need an identifier for compat hack.
> Hypervisor can detect buggy guests when they set status to OK without
> enabling bus master first.
> 
> Makes sense?

Ah, so you'd do the compat hack purely in qemu? Sounds good to me.

Nevermind the noise - please take that patch :-).

Alex

^ permalink raw reply

* Re: [PULL] virtio
From: Michael S. Tsirkin @ 2010-03-07 11:04 UTC (permalink / raw)
  To: Alexander Graf
  Cc: Shirley Ma, Jamie Lokier, linux-kernel, virtualization,
	Anthony Liguori, Amit Shah, Linus Torvalds, hch
In-Reply-To: <40B76F19-1E35-4956-A34E-0A83A403F97D@suse.de>

On Sun, Mar 07, 2010 at 11:57:23AM +0100, Alexander Graf wrote:
> 
> On 07.03.2010, at 11:42, Michael S. Tsirkin wrote:
> 
> > Linus,
> > Please pull another virtio fix: this one fixes hotplug and
> > was supposed to be applied by Rusty already
> > (http://lkml.org/lkml/2009/11/30/451), but apparently got lost,
> > somehow.
> > 
> > Thanks!
> > 
> > The following changes since commit 3119815912a220bdac943dfbdfee640414c0c611:
> >  Michael S. Tsirkin (1):
> >        virtio: fix out of range array access
> > 
> > are available in the git repository at:
> > 
> >  git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git for-linus
> > 
> > Michael S. Tsirkin (1):
> >      virtio: set pci bus master enable bit
> 
> This is still missing an identifier for the hypervisor. We need to know if the guest will ever set bus master enabled or not, so we can have a compat hack in qemu to not check for it.
> 
> 
> Alex

This patch fixes hotplug with qemu 0.11-0.12 which can't make use of a new
identifier without a time machine.

IMHO we can't add new identifiers in time for 2.6.34 anyway, so if you
want to do that, please send a patch and have it queued up for the next
release. But I don't think we need an identifier for compat hack.
Hypervisor can detect buggy guests when they set status to OK without
enabling bus master first.

Makes sense?


-- 
MST

^ permalink raw reply

* Re: [PULL] virtio
From: Alexander Graf @ 2010-03-07 10:57 UTC (permalink / raw)
  To: Michael S.Tsirkin
  Cc: Shirley Ma, Jamie Lokier, linux-kernel, virtualization,
	Anthony Liguori, Amit Shah, Linus Torvalds, hch
In-Reply-To: <20100307104252.GA19926@redhat.com>


On 07.03.2010, at 11:42, Michael S. Tsirkin wrote:

> Linus,
> Please pull another virtio fix: this one fixes hotplug and
> was supposed to be applied by Rusty already
> (http://lkml.org/lkml/2009/11/30/451), but apparently got lost,
> somehow.
> 
> Thanks!
> 
> The following changes since commit 3119815912a220bdac943dfbdfee640414c0c611:
>  Michael S. Tsirkin (1):
>        virtio: fix out of range array access
> 
> are available in the git repository at:
> 
>  git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git for-linus
> 
> Michael S. Tsirkin (1):
>      virtio: set pci bus master enable bit

This is still missing an identifier for the hypervisor. We need to know if the guest will ever set bus master enabled or not, so we can have a compat hack in qemu to not check for it.


Alex

^ permalink raw reply

* [PULL] virtio
From: Michael S. Tsirkin @ 2010-03-07 10:42 UTC (permalink / raw)
  To: Rusty Russell
  Cc: Shirley Ma, Jamie Lokier, linux-kernel, virtualization,
	Anthony Liguori, Amit Shah, Linus Torvalds, hch

Linus,
Please pull another virtio fix: this one fixes hotplug and
was supposed to be applied by Rusty already
(http://lkml.org/lkml/2009/11/30/451), but apparently got lost,
somehow.

Thanks!

The following changes since commit 3119815912a220bdac943dfbdfee640414c0c611:
  Michael S. Tsirkin (1):
        virtio: fix out of range array access

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git for-linus

Michael S. Tsirkin (1):
      virtio: set pci bus master enable bit

 drivers/virtio/virtio_pci.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

^ permalink raw reply

* Re: [PATCH 1/1] Stage: hv: Corrected all header comments to follow kernel-doc format-CORRECTED
From: Randy Dunlap @ 2010-03-04 22:37 UTC (permalink / raw)
  To: Hank Janssen
  Cc: 'linux-kernel@vger.kernel.org',
	devel@driverdev.osuosl.org, virtualization@lists.osdl.org,
	Haiyang Zhang, Hashir Abdi, Greg KH, joe@perches.com
In-Reply-To: <8AFC7968D54FB448A30D8F38F259C56217DC1B2C@TK5EX14MBXC116.redmond.corp.microsoft.com>

On Thu, 4 Mar 2010 22:11:00 +0000
Hank Janssen <hjanssen@microsoft.com> wrote:

> 
> From: Hank Janssen <hjanssen@microsoft.com>
> 
> Removed kerneldoc /** from functions that should not have them.
> Added proper kerneldoc headers to functions that should have them.
> 
> This includes fixes as pointed out by Randy Dunlap and Joe Perches.
> 
> Cc: Greg Kroah-Hartman <gregkh@suse.de>
> Cc: Joe Perches <joe@perches.com>
> Cc: Randy Dunlap <rdunlap@xenotime.net>
> Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
> Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>

Acked-by: Randy Dunlap <rdunlap@xenotime.net>

Thanks.

^ permalink raw reply

* [PATCH 1/1] Stage: hv: Corrected all header comments to follow kernel-doc format-CORRECTED
From: Hank Janssen @ 2010-03-04 22:11 UTC (permalink / raw)
  To: Hank Janssen, 'linux-kernel@vger.kernel.org',
	devel@driverdev.osuosl.org
  Cc: joe@perches.com, Greg KH, Haiyang Zhang, Hashir Abdi
In-Reply-To: <1FB5E1D5CA062146B38059374562DF725A908A11@TK5EX14MBXC126.redmond.corp.microsoft.com>


From: Hank Janssen <hjanssen@microsoft.com>

Removed kerneldoc /** from functions that should not have them.
Added proper kerneldoc headers to functions that should have them.

This includes fixes as pointed out by Randy Dunlap and Joe Perches.

Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: Joe Perches <joe@perches.com>
Cc: Randy Dunlap <rdunlap@xenotime.net>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>


---
 drivers/staging/hv/Channel.c     |   49 ++++++++++++++-----------
 drivers/staging/hv/ChannelMgmt.c |   33 +++++++++--------
 drivers/staging/hv/Connection.c  |   14 ++++----
 drivers/staging/hv/Hv.c          |   18 +++++-----
 drivers/staging/hv/NetVsc.c      |    8 ++--
 drivers/staging/hv/StorVsc.c     |   10 +++---
 drivers/staging/hv/TODO          |    1 -
 drivers/staging/hv/Vmbus.c       |   26 +++++++-------
 drivers/staging/hv/VmbusApi.h    |   18 +++++++++
 drivers/staging/hv/blkvsc_drv.c  |    6 ++--
 drivers/staging/hv/netvsc_drv.c  |    7 ++--
 drivers/staging/hv/osd.c         |   70 +++++++++++++++++++++++++++++++++++
 drivers/staging/hv/storvsc_drv.c |   14 ++++----
 drivers/staging/hv/vmbus_drv.c   |   74 +++++++++++++++++++++++++------------
 14 files changed, 234 insertions(+), 114 deletions(-)

diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
index d46eb14..1fc2710 100644
--- a/drivers/staging/hv/Channel.c
+++ b/drivers/staging/hv/Channel.c
@@ -64,8 +64,9 @@ static void DumpMonitorPage(struct hv_monitor_page *MonitorPage)
 }
 #endif

-/**
- * VmbusChannelSetEvent - Trigger an event notification on the specified channel.
+/*
+ * VmbusChannelSetEvent - Trigger an event notification on the specified
+ * channel.
  */
 static void VmbusChannelSetEvent(struct vmbus_channel *Channel)
 {
@@ -119,7 +120,7 @@ static void VmbusChannelClearEvent(struct vmbus_channel *channel)
 }

 #endif
-/**
+/*
  * VmbusChannelGetDebugInfo -Retrieve various channel debug info
  */
 void VmbusChannelGetDebugInfo(struct vmbus_channel *Channel,
@@ -164,7 +165,7 @@ void VmbusChannelGetDebugInfo(struct vmbus_channel *Channel,
        RingBufferGetDebugInfo(&Channel->Outbound, &DebugInfo->Outbound);
 }

-/**
+/*
  * VmbusChannelOpen - Open the specified channel.
  */
 int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize,
@@ -282,8 +283,9 @@ Cleanup:
        return 0;
 }

-/**
- * DumpGpadlBody - Dump the gpadl body message to the console for debugging purposes.
+/*
+ * DumpGpadlBody - Dump the gpadl body message to the console for
+ * debugging purposes.
  */
 static void DumpGpadlBody(struct vmbus_channel_gpadl_body *Gpadl, u32 Len)
 {
@@ -299,8 +301,9 @@ static void DumpGpadlBody(struct vmbus_channel_gpadl_body *Gpadl, u32 Len)
                           i, Gpadl->Pfn[i]);
 }

-/**
- * DumpGpadlHeader - Dump the gpadl header message to the console for debugging purposes.
+/*
+ * DumpGpadlHeader - Dump the gpadl header message to the console for
+ * debugging purposes.
  */
 static void DumpGpadlHeader(struct vmbus_channel_gpadl_header *Gpadl)
 {
@@ -324,7 +327,7 @@ static void DumpGpadlHeader(struct vmbus_channel_gpadl_header *Gpadl)
        }
 }

-/**
+/*
  * VmbusChannelCreateGpadlHeader - Creates a gpadl for the specified buffer
  */
 static int VmbusChannelCreateGpadlHeader(void *Kbuffer, u32 Size,
@@ -440,7 +443,7 @@ static int VmbusChannelCreateGpadlHeader(void *Kbuffer, u32 Size,
        return 0;
 }

-/**
+/*
  * VmbusChannelEstablishGpadl - Estabish a GPADL for the specified buffer
  *
  * @Channel: a channel
@@ -544,7 +547,7 @@ Cleanup:
        return ret;
 }

-/**
+/*
  * VmbusChannelTeardownGpadl -Teardown the specified GPADL handle
  */
 int VmbusChannelTeardownGpadl(struct vmbus_channel *Channel, u32 GpadlHandle)
@@ -597,7 +600,7 @@ int VmbusChannelTeardownGpadl(struct vmbus_channel *Channel, u32 GpadlHandle)
        return ret;
 }

-/**
+/*
  * VmbusChannelClose - Close the specified channel
  */
 void VmbusChannelClose(struct vmbus_channel *Channel)
@@ -662,7 +665,7 @@ void VmbusChannelClose(struct vmbus_channel *Channel)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelSendPacket - Send the specified buffer on the given channel
  */
 int VmbusChannelSendPacket(struct vmbus_channel *Channel, const void *Buffer,
@@ -708,8 +711,9 @@ int VmbusChannelSendPacket(struct vmbus_channel *Channel, const void *Buffer,
        return ret;
 }

-/**
- * VmbusChannelSendPacketPageBuffer - Send a range of single-page buffer packets using a GPADL Direct packet type.
+/*
+ * VmbusChannelSendPacketPageBuffer - Send a range of single-page buffer
+ * packets using a GPADL Direct packet type.
  */
 int VmbusChannelSendPacketPageBuffer(struct vmbus_channel *Channel,
                                     struct hv_page_buffer PageBuffers[],
@@ -773,8 +777,9 @@ int VmbusChannelSendPacketPageBuffer(struct vmbus_channel *Channel,
        return ret;
 }

-/**
- * VmbusChannelSendPacketMultiPageBuffer - Send a multi-page buffer packet using a GPADL Direct packet type.
+/*
+ * VmbusChannelSendPacketMultiPageBuffer - Send a multi-page buffer packet
+ * using a GPADL Direct packet type.
  */
 int VmbusChannelSendPacketMultiPageBuffer(struct vmbus_channel *Channel,
                                struct hv_multipage_buffer *MultiPageBuffer,
@@ -842,7 +847,7 @@ int VmbusChannelSendPacketMultiPageBuffer(struct vmbus_channel *Channel,
        return ret;
 }

-/**
+/*
  * VmbusChannelRecvPacket - Retrieve the user packet on the specified channel
  */
 /* TODO: Do we ever receive a gpa direct packet other than the ones we send ? */
@@ -908,7 +913,7 @@ int VmbusChannelRecvPacket(struct vmbus_channel *Channel, void *Buffer,
        return 0;
 }

-/**
+/*
  * VmbusChannelRecvPacketRaw - Retrieve the raw packet on the specified channel
  */
 int VmbusChannelRecvPacketRaw(struct vmbus_channel *Channel, void *Buffer,
@@ -971,7 +976,7 @@ int VmbusChannelRecvPacketRaw(struct vmbus_channel *Channel, void *Buffer,
        return 0;
 }

-/**
+/*
  * VmbusChannelOnChannelEvent - Channel event callback
  */
 void VmbusChannelOnChannelEvent(struct vmbus_channel *Channel)
@@ -984,7 +989,7 @@ void VmbusChannelOnChannelEvent(struct vmbus_channel *Channel)
        mod_timer(&Channel->poll_timer, jiffies + usecs_to_jiffies(100));
 }

-/**
+/*
  * VmbusChannelOnTimer - Timer event callback
  */
 void VmbusChannelOnTimer(unsigned long data)
@@ -995,7 +1000,7 @@ void VmbusChannelOnTimer(unsigned long data)
                channel->OnChannelCallback(channel->ChannelCallbackContext);
 }

-/**
+/*
  * DumpVmbusChannel - Dump vmbus channel info to the console
  */
 static void DumpVmbusChannel(struct vmbus_channel *Channel)
diff --git a/drivers/staging/hv/ChannelMgmt.c b/drivers/staging/hv/ChannelMgmt.c
index ef38467..cc4b93c 100644
--- a/drivers/staging/hv/ChannelMgmt.c
+++ b/drivers/staging/hv/ChannelMgmt.c
@@ -70,7 +70,7 @@ static const struct hv_guid
        },
 };

-/**
+/*
  * AllocVmbusChannel - Allocate and initialize a vmbus channel object
  */
 struct vmbus_channel *AllocVmbusChannel(void)
@@ -96,7 +96,7 @@ struct vmbus_channel *AllocVmbusChannel(void)
        return channel;
 }

-/**
+/*
  * ReleaseVmbusChannel - Release the vmbus channel object itself
  */
 static inline void ReleaseVmbusChannel(void *context)
@@ -114,7 +114,7 @@ static inline void ReleaseVmbusChannel(void *context)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * FreeVmbusChannel - Release the resources used by the vmbus channel object
  */
 void FreeVmbusChannel(struct vmbus_channel *Channel)
@@ -130,7 +130,7 @@ void FreeVmbusChannel(struct vmbus_channel *Channel)
                              Channel);
 }

-/**
+/*
  * VmbusChannelProcessOffer - Process the offer by creating a channel/device associated with this offer
  */
 static void VmbusChannelProcessOffer(void *context)
@@ -212,7 +212,7 @@ static void VmbusChannelProcessOffer(void *context)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelProcessRescindOffer - Rescind the offer by initiating a device removal
  */
 static void VmbusChannelProcessRescindOffer(void *context)
@@ -224,7 +224,7 @@ static void VmbusChannelProcessRescindOffer(void *context)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelOnOffer - Handler for channel offers from vmbus in parent partition.
  *
  * We ignore all offers except network and storage offers. For each network and
@@ -307,7 +307,7 @@ static void VmbusChannelOnOffer(struct vmbus_channel_message_header *hdr)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelOnOfferRescind - Rescind offer handler.
  *
  * We queue a work item to process this offer synchronously
@@ -334,7 +334,7 @@ static void VmbusChannelOnOfferRescind(struct vmbus_channel_message_header *hdr)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelOnOffersDelivered - This is invoked when all offers have been delivered.
  *
  * Nothing to do here.
@@ -346,7 +346,7 @@ static void VmbusChannelOnOffersDelivered(
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelOnOpenResult - Open result handler.
  *
  * This is invoked when we received a response to our channel open request.
@@ -394,7 +394,7 @@ static void VmbusChannelOnOpenResult(struct vmbus_channel_message_header *hdr)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelOnGpadlCreated - GPADL created handler.
  *
  * This is invoked when we received a response to our gpadl create request.
@@ -446,7 +446,7 @@ static void VmbusChannelOnGpadlCreated(struct vmbus_channel_message_header *hdr)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelOnGpadlTorndown - GPADL torndown handler.
  *
  * This is invoked when we received a response to our gpadl teardown request.
@@ -494,7 +494,7 @@ static void VmbusChannelOnGpadlTorndown(
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelOnVersionResponse - Version response handler
  *
  * This is invoked when we received a response to our initiate contact request.
@@ -557,7 +557,7 @@ static struct vmbus_channel_message_table_entry
        {ChannelMessageUnload,                  NULL},
 };

-/**
+/*
  * VmbusOnChannelMessage - Handler for channel protocol messages.
  *
  * This is invoked in the vmbus worker thread context.
@@ -596,7 +596,7 @@ void VmbusOnChannelMessage(void *Context)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelRequestOffers - Send a request to get all our pending offers.
  */
 int VmbusChannelRequestOffers(void)
@@ -650,8 +650,9 @@ Cleanup:
        return ret;
 }

-/**
- * VmbusChannelReleaseUnattachedChannels - Release channels that are unattached/unconnected ie (no drivers associated)
+/*
+ * VmbusChannelReleaseUnattachedChannels - Release channels that are
+ * unattached/unconnected ie (no drivers associated)
  */
 void VmbusChannelReleaseUnattachedChannels(void)
 {
diff --git a/drivers/staging/hv/Connection.c b/drivers/staging/hv/Connection.c
index 43c2e68..894aa37 100644
--- a/drivers/staging/hv/Connection.c
+++ b/drivers/staging/hv/Connection.c
@@ -33,7 +33,7 @@ struct VMBUS_CONNECTION gVmbusConnection = {
        .NextGpadlHandle        = ATOMIC_INIT(0xE1E10),
 };

-/**
+/*
  * VmbusConnect - Sends a connect request on the partition service connection
  */
 int VmbusConnect(void)
@@ -179,7 +179,7 @@ Cleanup:
        return ret;
 }

-/**
+/*
  * VmbusDisconnect - Sends a disconnect request on the partition service connection
  */
 int VmbusDisconnect(void)
@@ -217,7 +217,7 @@ Cleanup:
        return ret;
 }

-/**
+/*
  * GetChannelFromRelId - Get the channel object given its child relative id (ie channel id)
  */
 struct vmbus_channel *GetChannelFromRelId(u32 relId)
@@ -238,7 +238,7 @@ struct vmbus_channel *GetChannelFromRelId(u32 relId)
        return foundChannel;
 }

-/**
+/*
  * VmbusProcessChannelEvent - Process a channel event notification
  */
 static void VmbusProcessChannelEvent(void *context)
@@ -266,7 +266,7 @@ static void VmbusProcessChannelEvent(void *context)
        }
 }

-/**
+/*
  * VmbusOnEvents - Handler for events
  */
 void VmbusOnEvents(void)
@@ -307,7 +307,7 @@ void VmbusOnEvents(void)
        return;
 }

-/**
+/*
  * VmbusPostMessage - Send a msg on the vmbus's message connection
  */
 int VmbusPostMessage(void *buffer, size_t bufferLen)
@@ -319,7 +319,7 @@ int VmbusPostMessage(void *buffer, size_t bufferLen)
        return HvPostMessage(connId, 1, buffer, bufferLen);
 }

-/**
+/*
  * VmbusSetEvent - Send an event notification to the parent
  */
 int VmbusSetEvent(u32 childRelId)
diff --git a/drivers/staging/hv/Hv.c b/drivers/staging/hv/Hv.c
index 51149e6..9bee568 100644
--- a/drivers/staging/hv/Hv.c
+++ b/drivers/staging/hv/Hv.c
@@ -34,7 +34,7 @@ struct hv_context gHvContext = {
        .SignalEventBuffer      = NULL,
 };

-/**
+/*
  * HvQueryHypervisorPresence - Query the cpuid for presense of windows hypervisor
  */
 static int HvQueryHypervisorPresence(void)
@@ -55,7 +55,7 @@ static int HvQueryHypervisorPresence(void)
        return ecx & HV_PRESENT_BIT;
 }

-/**
+/*
  * HvQueryHypervisorInfo - Get version info of the windows hypervisor
  */
 static int HvQueryHypervisorInfo(void)
@@ -124,7 +124,7 @@ static int HvQueryHypervisorInfo(void)
        return maxLeaf;
 }

-/**
+/*
  * HvDoHypercall - Invoke the specified hypercall
  */
 static u64 HvDoHypercall(u64 Control, void *Input, void *Output)
@@ -179,7 +179,7 @@ static u64 HvDoHypercall(u64 Control, void *Input, void *Output)
 #endif /* !x86_64 */
 }

-/**
+/*
  * HvInit - Main initialization routine.
  *
  * This routine must be called before any other routines in here are called
@@ -293,7 +293,7 @@ Cleanup:
        return ret;
 }

-/**
+/*
  * HvCleanup - Cleanup routine.
  *
  * This routine is called normally during driver unloading or exiting.
@@ -320,7 +320,7 @@ void HvCleanup(void)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * HvPostMessage - Post a message using the hypervisor message IPC.
  *
  * This involves a hypercall.
@@ -361,7 +361,7 @@ u16 HvPostMessage(union hv_connection_id connectionId,
 }


-/**
+/*
  * HvSignalEvent - Signal an event on the specified connection using the hypervisor event IPC.
  *
  * This involves a hypercall.
@@ -375,7 +375,7 @@ u16 HvSignalEvent(void)
        return status;
 }

-/**
+/*
  * HvSynicInit - Initialize the Synthethic Interrupt Controller.
  *
  * If it is already initialized by another entity (ie x2v shim), we need to
@@ -481,7 +481,7 @@ Cleanup:
        return;
 }

-/**
+/*
  * HvSynicCleanup - Cleanup routine for HvSynicInit().
  */
 void HvSynicCleanup(void *arg)
diff --git a/drivers/staging/hv/NetVsc.c b/drivers/staging/hv/NetVsc.c
index 1c717f9..bd739ac 100644
--- a/drivers/staging/hv/NetVsc.c
+++ b/drivers/staging/hv/NetVsc.c
@@ -166,7 +166,7 @@ static struct netvsc_device *ReleaseInboundNetDevice(struct hv_device *Device)
        return netDevice;
 }

-/**
+/*
  * NetVscInitialize - Main entry point
  */
 int NetVscInitialize(struct hv_driver *drv)
@@ -704,7 +704,7 @@ static void NetVscDisconnectFromVsp(struct netvsc_device *NetDevice)
        DPRINT_EXIT(NETVSC);
 }

-/**
+/*
  * NetVscOnDeviceAdd - Callback when the device belonging to this driver is added
  */
 static int NetVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo)
@@ -806,7 +806,7 @@ Cleanup:
        return ret;
 }

-/**
+/*
  * NetVscOnDeviceRemove - Callback when the root bus device is removed
  */
 static int NetVscOnDeviceRemove(struct hv_device *Device)
@@ -863,7 +863,7 @@ static int NetVscOnDeviceRemove(struct hv_device *Device)
        return 0;
 }

-/**
+/*
  * NetVscOnCleanup - Perform any cleanup when the driver is removed
  */
 static void NetVscOnCleanup(struct hv_driver *drv)
diff --git a/drivers/staging/hv/StorVsc.c b/drivers/staging/hv/StorVsc.c
index 38ea140..5a09d08 100644
--- a/drivers/staging/hv/StorVsc.c
+++ b/drivers/staging/hv/StorVsc.c
@@ -532,7 +532,7 @@ static int StorVscConnectToVsp(struct hv_device *Device)
        return ret;
 }

-/**
+/*
  * StorVscOnDeviceAdd - Callback when the device belonging to this driver is added
  */
 static int StorVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo)
@@ -584,7 +584,7 @@ Cleanup:
        return ret;
 }

-/**
+/*
  * StorVscOnDeviceRemove - Callback when the our device is being removed
  */
 static int StorVscOnDeviceRemove(struct hv_device *Device)
@@ -682,7 +682,7 @@ Cleanup:
        return ret;
 }

-/**
+/*
  * StorVscOnIORequest - Callback to initiate an I/O request
  */
 static int StorVscOnIORequest(struct hv_device *Device,
@@ -782,7 +782,7 @@ static int StorVscOnIORequest(struct hv_device *Device,
        return ret;
 }

-/**
+/*
  * StorVscOnCleanup - Perform any cleanup when the driver is removed
  */
 static void StorVscOnCleanup(struct hv_driver *Driver)
@@ -791,7 +791,7 @@ static void StorVscOnCleanup(struct hv_driver *Driver)
        DPRINT_EXIT(STORVSC);
 }

-/**
+/*
  * StorVscInitialize - Main entry point
  */
 int StorVscInitialize(struct hv_driver *Driver)
diff --git a/drivers/staging/hv/TODO b/drivers/staging/hv/TODO
index dbfbde9..78d957e 100644
--- a/drivers/staging/hv/TODO
+++ b/drivers/staging/hv/TODO
@@ -1,6 +1,5 @@
 TODO:
        - fix remaining checkpatch warnings and errors
-       - use of /** when it is not a kerneldoc header
        - remove RingBuffer.c to us in-kernel ringbuffer functions instead.
        - audit the vmbus to verify it is working properly with the
          driver model
diff --git a/drivers/staging/hv/Vmbus.c b/drivers/staging/hv/Vmbus.c
index 3d0a240..9a6a340 100644
--- a/drivers/staging/hv/Vmbus.c
+++ b/drivers/staging/hv/Vmbus.c
@@ -51,7 +51,7 @@ static const struct hv_guid gVmbusDeviceId = {
 static struct hv_driver *gDriver; /* vmbus driver object */
 static struct hv_device *gDevice; /* vmbus root device */

-/**
+/*
  * VmbusGetChannelOffers - Retrieve the channel offers from the parent partition
  */
 static void VmbusGetChannelOffers(void)
@@ -61,7 +61,7 @@ static void VmbusGetChannelOffers(void)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusGetChannelInterface - Get the channel interface
  */
 static void VmbusGetChannelInterface(struct vmbus_channel_interface *Interface)
@@ -69,7 +69,7 @@ static void VmbusGetChannelInterface(struct vmbus_channel_interface *Interface)
        GetChannelInterface(Interface);
 }

-/**
+/*
  * VmbusGetChannelInfo - Get the device info for the specified device object
  */
 static void VmbusGetChannelInfo(struct hv_device *DeviceObject,
@@ -78,7 +78,7 @@ static void VmbusGetChannelInfo(struct hv_device *DeviceObject,
        GetChannelInfo(DeviceObject, DeviceInfo);
 }

-/**
+/*
  * VmbusCreateChildDevice - Creates the child device on the bus that represents the channel offer
  */
 struct hv_device *VmbusChildDeviceCreate(struct hv_guid *DeviceType,
@@ -91,7 +91,7 @@ struct hv_device *VmbusChildDeviceCreate(struct hv_guid *DeviceType,
                                                Context);
 }

-/**
+/*
  * VmbusChildDeviceAdd - Registers the child device with the vmbus
  */
 int VmbusChildDeviceAdd(struct hv_device *ChildDevice)
@@ -101,7 +101,7 @@ int VmbusChildDeviceAdd(struct hv_device *ChildDevice)
        return vmbusDriver->OnChildDeviceAdd(gDevice, ChildDevice);
 }

-/**
+/*
  * VmbusChildDeviceRemove Unregisters the child device from the vmbus
  */
 void VmbusChildDeviceRemove(struct hv_device *ChildDevice)
@@ -111,7 +111,7 @@ void VmbusChildDeviceRemove(struct hv_device *ChildDevice)
        vmbusDriver->OnChildDeviceRemove(ChildDevice);
 }

-/**
+/*
  * VmbusOnDeviceAdd - Callback when the root bus device is added
  */
 static int VmbusOnDeviceAdd(struct hv_device *dev, void *AdditionalInfo)
@@ -140,7 +140,7 @@ static int VmbusOnDeviceAdd(struct hv_device *dev, void *AdditionalInfo)
        return ret;
 }

-/**
+/*
  * VmbusOnDeviceRemove - Callback when the root bus device is removed
  */
 static int VmbusOnDeviceRemove(struct hv_device *dev)
@@ -156,7 +156,7 @@ static int VmbusOnDeviceRemove(struct hv_device *dev)
        return ret;
 }

-/**
+/*
  * VmbusOnCleanup - Perform any cleanup when the driver is removed
  */
 static void VmbusOnCleanup(struct hv_driver *drv)
@@ -168,7 +168,7 @@ static void VmbusOnCleanup(struct hv_driver *drv)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusOnMsgDPC - DPC routine to handle messages from the hypervisior
  */
 static void VmbusOnMsgDPC(struct hv_driver *drv)
@@ -216,7 +216,7 @@ static void VmbusOnMsgDPC(struct hv_driver *drv)
        }
 }

-/**
+/*
  * VmbusOnEventDPC - DPC routine to handle events from the hypervisior
  */
 static void VmbusOnEventDPC(struct hv_driver *drv)
@@ -225,7 +225,7 @@ static void VmbusOnEventDPC(struct hv_driver *drv)
        VmbusOnEvents();
 }

-/**
+/*
  * VmbusOnISR - ISR routine
  */
 static int VmbusOnISR(struct hv_driver *drv)
@@ -263,7 +263,7 @@ static int VmbusOnISR(struct hv_driver *drv)
        return ret;
 }

-/**
+/*
  * VmbusInitialize - Main entry point
  */
 int VmbusInitialize(struct hv_driver *drv)
diff --git a/drivers/staging/hv/VmbusApi.h b/drivers/staging/hv/VmbusApi.h
index d089bb1..d2d04bc 100644
--- a/drivers/staging/hv/VmbusApi.h
+++ b/drivers/staging/hv/VmbusApi.h
@@ -84,6 +84,24 @@ struct hv_device_info {
        struct hv_dev_port_info Outbound;
 };

+/**
+ * struct vmbus_channel_interface - Contains member functions for vmbus channel
+ * @Open:      Open the channel
+ * @Close:     Close the channel
+ * @SendPacket:        Send a packet over the channel
+ * @SendPacketPageBuffer:      Send a single page buffer over the channel
+ * @SendPacketMultiPageBuffer: Send a multiple page buffers
+ * @RecvPacket:        Receive packet
+ * @RecvPacketRaw:     Receive Raw packet
+ * @EstablishGpadl:    Set up GPADL for ringbuffer
+ * @TeardownGpadl:     Teardown GPADL for ringbuffer
+ * @GetInfo:   Get info about the channel
+ *
+ * This structure contains function pointer to control vmbus channel
+ * behavior. None of these functions is externally callable, but they
+ * are used for normal vmbus channel internal behavior.
+ * Only used by Hyper-V drivers.
+ */
 struct vmbus_channel_interface {
        int (*Open)(struct hv_device *Device, u32 SendBufferSize,
                    u32 RecvRingBufferSize, void *UserData, u32 UserDataLen,
diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
index abeac12..c90a6aa 100644
--- a/drivers/staging/hv/blkvsc_drv.c
+++ b/drivers/staging/hv/blkvsc_drv.c
@@ -164,7 +164,7 @@ static struct block_device_operations block_ops = {
        .ioctl  = blkvsc_ioctl,
 };

-/**
+/*
  * blkvsc_drv_init -  BlkVsc driver initialization.
  */
 static int blkvsc_drv_init(int (*drv_init)(struct hv_driver *drv))
@@ -244,7 +244,7 @@ static void blkvsc_drv_exit(void)
        return;
 }

-/**
+/*
  * blkvsc_probe - Add a new device for this driver
  */
 static int blkvsc_probe(struct device *device)
@@ -732,7 +732,7 @@ static int blkvsc_do_read_capacity16(struct block_device_context *blkdev)
        return 0;
 }

-/**
+/*
  * blkvsc_remove() - Callback when our device is removed
  */
 static int blkvsc_remove(struct device *device)
diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
index 1af3dcb..8b188d4 100644
--- a/drivers/staging/hv/netvsc_drv.c
+++ b/drivers/staging/hv/netvsc_drv.c
@@ -265,7 +265,7 @@ retry_send:
        return ret;
 }

-/**
+/*
  * netvsc_linkstatus_callback - Link up/down notification
  */
 static void netvsc_linkstatus_callback(struct hv_device *device_obj,
@@ -292,8 +292,9 @@ static void netvsc_linkstatus_callback(struct hv_device *device_obj,
        DPRINT_EXIT(NETVSC_DRV);
 }

-/**
- * netvsc_recv_callback -  Callback when we receive a packet from the "wire" on the specified device.
+/*
+ * netvsc_recv_callback -  Callback when we receive a packet from the
+ * "wire" on the specified device.
  */
 static int netvsc_recv_callback(struct hv_device *device_obj,
                                struct hv_netvsc_packet *packet)
diff --git a/drivers/staging/hv/osd.c b/drivers/staging/hv/osd.c
index 3a4793a..6b785e6 100644
--- a/drivers/staging/hv/osd.c
+++ b/drivers/staging/hv/osd.c
@@ -58,6 +58,15 @@ void *osd_VirtualAllocExec(unsigned int size)
 #endif
 }

+/**
+ * osd_PageAlloc() - Allocate pages
+ * @count:      Total number of Kernel pages you want to allocate
+ *
+ * Tries to allocate @count number of consecutive free kernel pages.
+ * And if successful, it will set the pages to 0 before returning.
+ * If successfull it will return pointer to the @count pages.
+ * Mainly used by Hyper-V drivers.
+ */
 void *osd_PageAlloc(unsigned int count)
 {
        void *p;
@@ -77,6 +86,14 @@ void *osd_PageAlloc(unsigned int count)
 }
 EXPORT_SYMBOL_GPL(osd_PageAlloc);

+/**
+ * osd_PageFree() - Free pages
+ * @page:       Pointer to the first page to be freed
+ * @count:      Total number of Kernel pages you free
+ *
+ * Frees the pages allocated by osd_PageAlloc()
+ * Mainly used by Hyper-V drivers.
+ */
 void osd_PageFree(void *page, unsigned int count)
 {
        free_pages((unsigned long)page, get_order(count * PAGE_SIZE));
@@ -85,6 +102,17 @@ void osd_PageFree(void *page, unsigned int count)
 }
 EXPORT_SYMBOL_GPL(osd_PageFree);

+/**
+ * osd_WaitEventCreate() - Create the event queue
+ *
+ * Allocates memory for a &struct osd_waitevent. And then calls
+ * init_waitqueue_head to set up the wait queue for the event.
+ * This structure is usually part of a another structure that contains
+ * the actual Hyper-V device driver structure.
+ *
+ * Returns pointer to &struct osd_waitevent
+ * Mainly used by Hyper-V drivers.
+ */
 struct osd_waitevent *osd_WaitEventCreate(void)
 {
        struct osd_waitevent *wait = kmalloc(sizeof(struct osd_waitevent),
@@ -98,6 +126,19 @@ struct osd_waitevent *osd_WaitEventCreate(void)
 }
 EXPORT_SYMBOL_GPL(osd_WaitEventCreate);

+
+/**
+ * osd_WaitEventSet() - Wake up the process
+ * @waitEvent: Structure to event to be woken up
+ *
+ * @waitevent is of type &struct osd_waitevent
+ *
+ * Wake up the sleeping process so it can do some work.
+ * And set condition indicator in &struct osd_waitevent to indicate
+ * the process is in a woken state.
+ *
+ * Only used by Network and Storage Hyper-V drivers.
+ */
 void osd_WaitEventSet(struct osd_waitevent *waitEvent)
 {
        waitEvent->condition = 1;
@@ -105,6 +146,20 @@ void osd_WaitEventSet(struct osd_waitevent *waitEvent)
 }
 EXPORT_SYMBOL_GPL(osd_WaitEventSet);

+/**
+ * osd_WaitEventWait() - Wait for event till condition is true
+ * @waitEvent: Structure to event to be put to sleep
+ *
+ * @waitevent is of type &struct osd_waitevent
+ *
+ * Set up the process to sleep until waitEvent->condition get true.
+ * And set condition indicator in &struct osd_waitevent to indicate
+ * the process is in a sleeping state.
+ *
+ * Returns the status of 'wait_event_interruptible()' system call
+ *
+ * Mainly used by Hyper-V drivers.
+ */
 int osd_WaitEventWait(struct osd_waitevent *waitEvent)
 {
        int ret = 0;
@@ -116,6 +171,21 @@ int osd_WaitEventWait(struct osd_waitevent *waitEvent)
 }
 EXPORT_SYMBOL_GPL(osd_WaitEventWait);

+/**
+ * osd_WaitEventWaitEx() - Wait for event or timeout for process wakeup
+ * @waitEvent: Structure to event to be put to sleep
+ * @TimeoutInMs:       Total number of Milliseconds to wait before waking up
+ *
+ * @waitevent is of type &struct osd_waitevent
+ * Set up the process to sleep until @waitEvent->condition get true or
+ * @TimeoutInMs (Time out in Milliseconds) has been reached.
+ * And set condition indicator in &struct osd_waitevent to indicate
+ * the process is in a sleeping state.
+ *
+ * Returns the status of 'wait_event_interruptible_timeout()' system call
+ *
+ * Mainly used by Hyper-V drivers.
+ */
 int osd_WaitEventWaitEx(struct osd_waitevent *waitEvent, u32 TimeoutInMs)
 {
        int ret = 0;
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 3988f4b..7676ba5 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -129,7 +129,7 @@ static struct scsi_host_template scsi_driver = {
 };


-/**
+/*
  * storvsc_drv_init - StorVsc driver initialization.
  */
 static int storvsc_drv_init(int (*drv_init)(struct hv_driver *drv))
@@ -222,7 +222,7 @@ static void storvsc_drv_exit(void)
        return;
 }

-/**
+/*
  * storvsc_probe - Add a new device for this driver
  */
 static int storvsc_probe(struct device *device)
@@ -318,7 +318,7 @@ static int storvsc_probe(struct device *device)
        return ret;
 }

-/**
+/*
  * storvsc_remove - Callback when our device is removed
  */
 static int storvsc_remove(struct device *device)
@@ -371,7 +371,7 @@ static int storvsc_remove(struct device *device)
        return ret;
 }

-/**
+/*
  * storvsc_commmand_completion - Command completion processing
  */
 static void storvsc_commmand_completion(struct hv_storvsc_request *request)
@@ -622,7 +622,7 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
        return total_copied;
 }

-/**
+/*
  * storvsc_queuecommand - Initiate command processing
  */
 static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
@@ -823,7 +823,7 @@ static int storvsc_merge_bvec(struct request_queue *q,
        return bvec->bv_len;
 }

-/**
+/*
  * storvsc_device_configure - Configure the specified scsi device
  */
 static int storvsc_device_alloc(struct scsi_device *sdevice)
@@ -862,7 +862,7 @@ static int storvsc_device_configure(struct scsi_device *sdevice)
        return 0;
 }

-/**
+/*
  * storvsc_host_reset_handler - Reset the scsi HBA
  */
 static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
index 2c90619..177f565 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/staging/hv/vmbus_drv.c
@@ -128,7 +128,7 @@ static struct vmbus_driver_context g_vmbus_drv = {
        .bus.dev_attrs =        vmbus_device_attrs,
 };

-/**
+/*
  * vmbus_show_device_attr - Show the device attribute in sysfs.
  *
  * This is invoked when user does a
@@ -232,7 +232,7 @@ static ssize_t vmbus_show_device_attr(struct device *dev,
        }
 }

-/**
+/*
  * vmbus_bus_init -Main vmbus driver initialization routine.
  *
  * Here, we
@@ -361,7 +361,7 @@ cleanup:
        return ret;
 }

-/**
+/*
  * vmbus_bus_exit - Terminate the vmbus driver.
  *
  * This routine is opposite of vmbus_bus_init()
@@ -397,8 +397,18 @@ static void vmbus_bus_exit(void)
        return;
 }

+
 /**
- * vmbus_child_driver_register - Register a vmbus's child driver
+ * vmbus_child_driver_register() - Register a vmbus's child driver
+ * @driver_ctx:        Pointer to driver structure you want to register
+ *
+ * @driver_ctx is of type &struct driver_context
+ *
+ * Registers the given driver with Linux through the 'driver_register()' call
+ * And sets up the hyper-v vmbus handling for this driver.
+ * It will return the state of the 'driver_register()' call.
+ *
+ * Mainly used by Hyper-V drivers.
  */
 int vmbus_child_driver_register(struct driver_context *driver_ctx)
 {
@@ -424,7 +434,15 @@ int vmbus_child_driver_register(struct driver_context *driver_ctx)
 EXPORT_SYMBOL(vmbus_child_driver_register);

 /**
- * vmbus_child_driver_unregister Unregister a vmbus's child driver
+ * vmbus_child_driver_unregister() - Unregister a vmbus's child driver
+ * @driver_ctx:        Pointer to driver structure you want to un-register
+ *
+ * @driver_ctx is of type &struct driver_context
+ *
+ * Un-register the given driver with Linux through the 'driver_unregister()'
+ * call. And ungegisters the driver from the Hyper-V vmbus handler.
+ *
+ * Mainly used by Hyper-V drivers.
  */
 void vmbus_child_driver_unregister(struct driver_context *driver_ctx)
 {
@@ -442,9 +460,15 @@ void vmbus_child_driver_unregister(struct driver_context *driver_ctx)
 EXPORT_SYMBOL(vmbus_child_driver_unregister);

 /**
- * vmbus_get_interface - Get the vmbus channel interface.
+ * vmbus_get_interface() - Get the vmbus channel interface.
+ * @interface: Pointer to channel interface structure
+ *
+ * Get the Hyper-V channel used for the driver.
+ *
+ * @interface is of type &struct vmbus_channel_interface
+ * This is invoked by child/client driver that sits above vmbus.
  *
- * This is invoked by child/client driver that sits above vmbus
+ * Mainly used by Hyper-V drivers.
  */
 void vmbus_get_interface(struct vmbus_channel_interface *interface)
 {
@@ -454,7 +478,7 @@ void vmbus_get_interface(struct vmbus_channel_interface *interface)
 }
 EXPORT_SYMBOL(vmbus_get_interface);

-/**
+/*
  * vmbus_child_device_get_info - Get the vmbus child device info.
  *
  * This is invoked to display various device attributes in sysfs.
@@ -467,8 +491,9 @@ static void vmbus_child_device_get_info(struct hv_device *device_obj,
        vmbus_drv_obj->GetChannelInfo(device_obj, device_info);
 }

-/**
- * vmbus_child_device_create - Creates and registers a new child device on the vmbus.
+/*
+ * vmbus_child_device_create - Creates and registers a new child device
+ * on the vmbus.
  */
 static struct hv_device *vmbus_child_device_create(struct hv_guid *type,
                                                   struct hv_guid *instance,
@@ -522,7 +547,7 @@ static struct hv_device *vmbus_child_device_create(struct hv_guid *type,
        return child_device_obj;
 }

-/**
+/*
  * vmbus_child_device_register - Register the child device on the specified bus
  */
 static int vmbus_child_device_register(struct hv_device *root_device_obj,
@@ -570,8 +595,9 @@ static int vmbus_child_device_register(struct hv_device *root_device_obj,
        return ret;
 }

-/**
- * vmbus_child_device_unregister - Remove the specified child device from the vmbus.
+/*
+ * vmbus_child_device_unregister - Remove the specified child device
+ * from the vmbus.
  */
 static void vmbus_child_device_unregister(struct hv_device *device_obj)
 {
@@ -594,7 +620,7 @@ static void vmbus_child_device_unregister(struct hv_device *device_obj)
        DPRINT_EXIT(VMBUS_DRV);
 }

-/**
+/*
  * vmbus_child_device_destroy - Destroy the specified child device on the vmbus.
  */
 static void vmbus_child_device_destroy(struct hv_device *device_obj)
@@ -604,7 +630,7 @@ static void vmbus_child_device_destroy(struct hv_device *device_obj)
        DPRINT_EXIT(VMBUS_DRV);
 }

-/**
+/*
  * vmbus_uevent - add uevent for our device
  *
  * This routine is invoked when a device is added or removed on the vmbus to
@@ -683,7 +709,7 @@ static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
        return 0;
 }

-/**
+/*
  * vmbus_match - Attempt to match the specified device to the specified driver
  */
 static int vmbus_match(struct device *device, struct device_driver *driver)
@@ -718,7 +744,7 @@ static int vmbus_match(struct device *device, struct device_driver *driver)
        return match;
 }

-/**
+/*
  * vmbus_probe_failed_cb - Callback when a driver probe failed in vmbus_probe()
  *
  * We need a callback because we cannot invoked device_unregister() inside
@@ -741,7 +767,7 @@ static void vmbus_probe_failed_cb(struct work_struct *context)
        DPRINT_EXIT(VMBUS_DRV);
 }

-/**
+/*
  * vmbus_probe - Add the new vmbus's child device
  */
 static int vmbus_probe(struct device *child_device)
@@ -777,7 +803,7 @@ static int vmbus_probe(struct device *child_device)
        return ret;
 }

-/**
+/*
  * vmbus_remove - Remove a vmbus device
  */
 static int vmbus_remove(struct device *child_device)
@@ -819,7 +845,7 @@ static int vmbus_remove(struct device *child_device)
        return 0;
 }

-/**
+/*
  * vmbus_shutdown - Shutdown a vmbus device
  */
 static void vmbus_shutdown(struct device *child_device)
@@ -855,7 +881,7 @@ static void vmbus_shutdown(struct device *child_device)
        return;
 }

-/**
+/*
  * vmbus_bus_release - Final callback release of the vmbus root device
  */
 static void vmbus_bus_release(struct device *device)
@@ -869,7 +895,7 @@ static void vmbus_bus_release(struct device *device)
        DPRINT_EXIT(VMBUS_DRV);
 }

-/**
+/*
  * vmbus_device_release - Final callback release of the vmbus child device
  */
 static void vmbus_device_release(struct device *device)
@@ -887,7 +913,7 @@ static void vmbus_device_release(struct device *device)
        return;
 }

-/**
+/*
  * vmbus_msg_dpc - Tasklet routine to handle hypervisor messages
  */
 static void vmbus_msg_dpc(unsigned long data)
@@ -904,7 +930,7 @@ static void vmbus_msg_dpc(unsigned long data)
        DPRINT_EXIT(VMBUS_DRV);
 }

-/**
+/*
  * vmbus_msg_dpc - Tasklet routine to handle hypervisor events
  */
 static void vmbus_event_dpc(unsigned long data)

^ permalink raw reply related

* RE: [PATCH 1/1] Stage: hv: Corrected all header comments to follow kernel-doc format
From: Hank Janssen @ 2010-03-04 18:11 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: 'linux-kernel@vger.kernel.org',
	devel@driverdev.osuosl.org, virtualization@lists.osdl.org,
	Greg KH, Haiyang Zhang, Hashir Abdi
In-Reply-To: <20100304100352.d7bd75fb.rdunlap@xenotime.net>



Randy and Joe,

Thanks for the feedback, let me correct it (not sure why the lines are messed up :() and resubmit!

Thanks,

Hank

^ permalink raw reply

* Re: [PATCH 1/1] Stage: hv: Corrected all header comments to follow kernel-doc format
From: Randy Dunlap @ 2010-03-04 18:03 UTC (permalink / raw)
  To: Hank Janssen
  Cc: 'linux-kernel@vger.kernel.org',
	devel@driverdev.osuosl.org, virtualization@lists.osdl.org,
	Greg KH, Haiyang Zhang, Hashir Abdi
In-Reply-To: <8AFC7968D54FB448A30D8F38F259C56217DBFDF9@TK5EX14MBXC116.redmond.corp.microsoft.com>

On Thu, 4 Mar 2010 17:48:18 +0000 Hank Janssen wrote:

> 
> From: Hank Janssen <hjanssen@microsoft.com>
> 
> Removed kerneldoc /** from functions that should not have them.
> Added proper kerneldoc headers to functions that should have them.

Hi,

Most of the patch looks good.  I found a few nits to pick.
Please see below.

> Cc: Greg Kroah-Hartman <gregkh@suse.de>
> Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
> Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
> 
> ---
>  drivers/staging/hv/Channel.c     |   49 ++++++++++++++-----------
>  drivers/staging/hv/ChannelMgmt.c |   33 +++++++++--------
>  drivers/staging/hv/Connection.c  |   14 ++++----
>  drivers/staging/hv/Hv.c          |   18 +++++-----
>  drivers/staging/hv/NetVsc.c      |    8 ++--
>  drivers/staging/hv/StorVsc.c     |   10 +++---
>  drivers/staging/hv/TODO          |    1 -
>  drivers/staging/hv/Vmbus.c       |   26 +++++++-------
>  drivers/staging/hv/VmbusApi.h    |   19 ++++++++++
>  drivers/staging/hv/blkvsc_drv.c  |    6 ++--
>  drivers/staging/hv/netvsc_drv.c  |    4 +-
>  drivers/staging/hv/osd.c         |   70 +++++++++++++++++++++++++++++++++++
>  drivers/staging/hv/storvsc_drv.c |   14 ++++----
>  drivers/staging/hv/vmbus_drv.c   |   74 +++++++++++++++++++++++++------------
>  14 files changed, 233 insertions(+), 113 deletions(-)



diff --git a/drivers/staging/hv/VmbusApi.h b/drivers/staging/hv/VmbusApi.h index d089bb1..2e3a3b8 100644
> --- a/drivers/staging/hv/VmbusApi.h
> +++ b/drivers/staging/hv/VmbusApi.h
> @@ -84,6 +84,25 @@ struct hv_device_info {
>         struct hv_dev_port_info Outbound;
>  };
> 
> +/**
> + * struct vmbus_channel_interface - Contains member functions for vmbus channel
> + * @Open:      Open the channel
> + * @Close:     Close the channel
> + * @SendPacket:        Send a packet over the channel
> + * @SendPacketPageBuffer:      Send a single page buffer over the channel
> + * @SendPacketMultiPageBuffer: Send a multiple page buffers
> + * @RecvPacket:        Receive packet
> + * @RecvPacketRaw:     Receive Raw packet
> + * @EstablishGpadl:    Set up GPADL for ringbuffer
> + * @TeardownGpadl:     Teardown GPADL for ringbuffer
> + * @GetInfo:   Get info about the channel
> + *
> + * This structure contains function pointer to control vmbus channel
> + * behavior.
> + * None of these functions is externally callable, but they are used
> +for normal

There appears to be some unwanted line breaking ^here^.

> + * vmbus channel internal behavior.
> + * Only used by Hyper-V drivers.
> + */
>  struct vmbus_channel_interface {
>         int (*Open)(struct hv_device *Device, u32 SendBufferSize,
>                     u32 RecvRingBufferSize, void *UserData, u32 UserDataLen, diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index abeac12..c90a6aa 100644


and why are those 2 lines above joined/merged?
I suspect that it will be a bit difficult for Greg to apply this patch.


diff --git a/drivers/staging/hv/osd.c b/drivers/staging/hv/osd.c index 3a4793a..5afa94e 100644
> --- a/drivers/staging/hv/osd.c
> +++ b/drivers/staging/hv/osd.c
> @@ -77,6 +86,14 @@ void *osd_PageAlloc(unsigned int count)  }  EXPORT_SYMBOL_GPL(osd_PageAlloc);
> 
> +/**
> + * osd_PageFree() - Free pages
> + * @page:       Pointer to the first page to be freed
> + * @count:      Total number of Kernel pages you free
> + *
> + * Frees the pages allocated by osd_PageAlloc()
> + * Mainly used by Hyper-V drivers.
> + */
>  void osd_PageFree(void *page, unsigned int count)  {
>         free_pages((unsigned long)page, get_order(count * PAGE_SIZE)); @@ -85,6 +102,17 @@ void osd_PageFree(void *page, unsigned int count)  }  EXPORT_SYMBOL_GPL(osd_PageFree);
> 
> +/**
> + * osd_WaitEventCreate() - Create the event queue
> + *
> + * Allocates memory for a &struct osd_waitevent. And than calls

aha.  Correct struct reference, using '&'.  :)

> + * init_waitqueue_head to set up the wait queue for the event.
> + * This structure is usually part of a another structure that contains
> + * the actual Hyper-V device driver structure.
> + *
> + * Returns pointer to &struct osd_waitevent
> + * Mainly used by Hyper-V drivers.
> + */
>  struct osd_waitevent *osd_WaitEventCreate(void)  {
>         struct osd_waitevent *wait = kmalloc(sizeof(struct osd_waitevent), @@ -98,6 +126,19 @@ struct osd_waitevent *osd_WaitEventCreate(void)  }  EXPORT_SYMBOL_GPL(osd_WaitEventCreate);
> 
> +
> +/**
> + * osd_WaitEventSet() - Wake up the process
> + * @waitEvent: Structure to event to be woken up
> + *
> + * @waitevent is of type @struct osd_waitevent

Use '&' here also.

> + *
> + * Wake up the sleeping process so it can do some work.
> + * And set condition indicator in struct osd_waitevent to indicate
> + * the process is in a woken state.
> + *
> + * Only used by Network and Storage Hyper-V drivers.
> + */
>  void osd_WaitEventSet(struct osd_waitevent *waitEvent)  {
>         waitEvent->condition = 1;
> @@ -105,6 +146,20 @@ void osd_WaitEventSet(struct osd_waitevent *waitEvent)  }  EXPORT_SYMBOL_GPL(osd_WaitEventSet);
> 
> +/**
> + * osd_WaitEventWait() - Wait for event till condition is true
> + * @waitEvent: Structure to event to be put to sleep
> + *
> + * @waitevent is of type @struct osd_waitevent

Use '&' here also.

> + *
> + * Set up the process to sleep until waitEvent->condition get true.
> + * And set condition indicator in struct osd_waitevent to indicate
> + * the process is in a sleeping state.
> + *
> + * Returns the status of 'wait_event_interruptible()' system call
> + *
> + * Mainly used by Hyper-V drivers.
> + */
>  int osd_WaitEventWait(struct osd_waitevent *waitEvent)  {
>         int ret = 0;
> @@ -116,6 +171,21 @@ int osd_WaitEventWait(struct osd_waitevent *waitEvent)  }  EXPORT_SYMBOL_GPL(osd_WaitEventWait);
> 
> +/**
> + * osd_WaitEventWaitEx() - Wait for event or timeout for process wakeup
> + * @waitEvent: Structure to event to be put to sleep
> + * @TimeoutInMs:       Total number of Milliseconds to wait before waking up
> + *
> + * @waitevent is of type @struct osd_waitevent

Use '&' here also.

> + * Set up the process to sleep until @waitEvent->condition get true or
> + * @TimeoutInMs (Time out in Milliseconds) has been reached.
> + * And set condition indicator in struct osd_waitevent to indicate
> + * the process is in a sleeping state.
> + *
> + * Returns the status of 'wait_event_interruptible_timeout()' system
> +call
> + *
> + * Mainly used by Hyper-V drivers.
> + */
>  int osd_WaitEventWaitEx(struct osd_waitevent *waitEvent, u32 TimeoutInMs)  {
>         int ret = 0;



---
~Randy

^ permalink raw reply

* Re: [PATCH 1/1] Stage: hv: Corrected all header comments to follow kernel-doc format
From: Joe Perches @ 2010-03-04 17:55 UTC (permalink / raw)
  To: Hank Janssen
  Cc: 'linux-kernel@vger.kernel.org',
	devel@driverdev.osuosl.org, virtualization@lists.osdl.org,
	Haiyang Zhang, Hashir Abdi, Greg KH
In-Reply-To: <8AFC7968D54FB448A30D8F38F259C56217DBFDF9@TK5EX14MBXC116.redmond.corp.microsoft.com>

On Thu, 2010-03-04 at 17:48 +0000, Hank Janssen wrote:
> From: Hank Janssen <hjanssen@microsoft.com>
> 
> Removed kerneldoc /** from functions that should not have them.
> Added proper kerneldoc headers to functions that should have them.
> diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c index d46eb14..1fc2710 100644
> --- a/drivers/staging/hv/Channel.c
> +++ b/drivers/staging/hv/Channel.c
> @@ -64,8 +64,9 @@ static void DumpMonitorPage(struct hv_monitor_page *MonitorPage)  }  #endif
> 
> -/**
> - * VmbusChannelSetEvent - Trigger an event notification on the specified channel.
> +/*
> + * VmbusChannelSetEvent - Trigger an event notification on the
> +specified
> + * channel.
>   */
>  static void VmbusChannelSetEvent(struct vmbus_channel *Channel)  { @@ -119,7 +120,7 @@ static void VmbusChannelClearEvent(struct vmbus_channel *channel)  }
> 
>  #endif

Yuck.

I don't know what you used for comment wrapping,
but it's broken here and in a bunch of other places.

Some are shown below:

[]

> -/**
> - * VmbusChannelSendPacketPageBuffer - Send a range of single-page buffer packets using a GPADL Direct packet type.
> +/*
> + * VmbusChannelSendPacketPageBuffer - Send a range of single-page
> +buffer
> + * packets using a GPADL Direct packet type.
>   */
>  int VmbusChannelSendPacketPageBuffer(struct vmbus_channel *Channel,
>                                      struct hv_page_buffer PageBuffers[], @@ -773,8 +777,9 @@ int VmbusChannelSendPacketPageBuffer(struct vmbus_channel *Channel,
>         return ret;
>  }
> 
> -/**
> - * VmbusChannelSendPacketMultiPageBuffer - Send a multi-page buffer packet using a GPADL Direct packet type.
> +/*
> + * VmbusChannelSendPacketMultiPageBuffer - Send a multi-page buffer
> +packet
> + * using a GPADL Direct packet type.
>   */
>  int VmbusChannelSendPacketMultiPageBuffer(struct vmbus_channel *Channel,
>                                 struct hv_multipage_buffer *MultiPageBuffer, @@ -842,7 +847,7 @@ int VmbusChannelSendPacketMultiPageBuffer(struct vmbus_channel *Channel,
>         return ret;
>  }

^ permalink raw reply

* [PATCH 1/1] Stage: hv: Corrected all header comments to follow kernel-doc format
From: Hank Janssen @ 2010-03-04 17:48 UTC (permalink / raw)
  To: 'linux-kernel@vger.kernel.org',
	devel@driverdev.osuosl.org, virtualization@lists.osdl.org
  Cc: Haiyang Zhang, Hashir Abdi, Greg KH
In-Reply-To: <1FB5E1D5CA062146B38059374562DF725A908A11@TK5EX14MBXC126.redmond.corp.microsoft.com>


From: Hank Janssen <hjanssen@microsoft.com>

Removed kerneldoc /** from functions that should not have them.
Added proper kerneldoc headers to functions that should have them.

Cc: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>

---
 drivers/staging/hv/Channel.c     |   49 ++++++++++++++-----------
 drivers/staging/hv/ChannelMgmt.c |   33 +++++++++--------
 drivers/staging/hv/Connection.c  |   14 ++++----
 drivers/staging/hv/Hv.c          |   18 +++++-----
 drivers/staging/hv/NetVsc.c      |    8 ++--
 drivers/staging/hv/StorVsc.c     |   10 +++---
 drivers/staging/hv/TODO          |    1 -
 drivers/staging/hv/Vmbus.c       |   26 +++++++-------
 drivers/staging/hv/VmbusApi.h    |   19 ++++++++++
 drivers/staging/hv/blkvsc_drv.c  |    6 ++--
 drivers/staging/hv/netvsc_drv.c  |    4 +-
 drivers/staging/hv/osd.c         |   70 +++++++++++++++++++++++++++++++++++
 drivers/staging/hv/storvsc_drv.c |   14 ++++----
 drivers/staging/hv/vmbus_drv.c   |   74 +++++++++++++++++++++++++------------
 14 files changed, 233 insertions(+), 113 deletions(-)

diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c index d46eb14..1fc2710 100644
--- a/drivers/staging/hv/Channel.c
+++ b/drivers/staging/hv/Channel.c
@@ -64,8 +64,9 @@ static void DumpMonitorPage(struct hv_monitor_page *MonitorPage)  }  #endif

-/**
- * VmbusChannelSetEvent - Trigger an event notification on the specified channel.
+/*
+ * VmbusChannelSetEvent - Trigger an event notification on the
+specified
+ * channel.
  */
 static void VmbusChannelSetEvent(struct vmbus_channel *Channel)  { @@ -119,7 +120,7 @@ static void VmbusChannelClearEvent(struct vmbus_channel *channel)  }

 #endif
-/**
+/*
  * VmbusChannelGetDebugInfo -Retrieve various channel debug info
  */
 void VmbusChannelGetDebugInfo(struct vmbus_channel *Channel, @@ -164,7 +165,7 @@ void VmbusChannelGetDebugInfo(struct vmbus_channel *Channel,
        RingBufferGetDebugInfo(&Channel->Outbound, &DebugInfo->Outbound);  }

-/**
+/*
  * VmbusChannelOpen - Open the specified channel.
  */
 int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize, @@ -282,8 +283,9 @@ Cleanup:
        return 0;
 }

-/**
- * DumpGpadlBody - Dump the gpadl body message to the console for debugging purposes.
+/*
+ * DumpGpadlBody - Dump the gpadl body message to the console for
+ * debugging purposes.
  */
 static void DumpGpadlBody(struct vmbus_channel_gpadl_body *Gpadl, u32 Len)  { @@ -299,8 +301,9 @@ static void DumpGpadlBody(struct vmbus_channel_gpadl_body *Gpadl, u32 Len)
                           i, Gpadl->Pfn[i]);
 }

-/**
- * DumpGpadlHeader - Dump the gpadl header message to the console for debugging purposes.
+/*
+ * DumpGpadlHeader - Dump the gpadl header message to the console for
+ * debugging purposes.
  */
 static void DumpGpadlHeader(struct vmbus_channel_gpadl_header *Gpadl)  { @@ -324,7 +327,7 @@ static void DumpGpadlHeader(struct vmbus_channel_gpadl_header *Gpadl)
        }
 }

-/**
+/*
  * VmbusChannelCreateGpadlHeader - Creates a gpadl for the specified buffer
  */
 static int VmbusChannelCreateGpadlHeader(void *Kbuffer, u32 Size, @@ -440,7 +443,7 @@ static int VmbusChannelCreateGpadlHeader(void *Kbuffer, u32 Size,
        return 0;
 }

-/**
+/*
  * VmbusChannelEstablishGpadl - Estabish a GPADL for the specified buffer
  *
  * @Channel: a channel
@@ -544,7 +547,7 @@ Cleanup:
        return ret;
 }

-/**
+/*
  * VmbusChannelTeardownGpadl -Teardown the specified GPADL handle
  */
 int VmbusChannelTeardownGpadl(struct vmbus_channel *Channel, u32 GpadlHandle) @@ -597,7 +600,7 @@ int VmbusChannelTeardownGpadl(struct vmbus_channel *Channel, u32 GpadlHandle)
        return ret;
 }

-/**
+/*
  * VmbusChannelClose - Close the specified channel
  */
 void VmbusChannelClose(struct vmbus_channel *Channel) @@ -662,7 +665,7 @@ void VmbusChannelClose(struct vmbus_channel *Channel)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelSendPacket - Send the specified buffer on the given channel
  */
 int VmbusChannelSendPacket(struct vmbus_channel *Channel, const void *Buffer, @@ -708,8 +711,9 @@ int VmbusChannelSendPacket(struct vmbus_channel *Channel, const void *Buffer,
        return ret;
 }

-/**
- * VmbusChannelSendPacketPageBuffer - Send a range of single-page buffer packets using a GPADL Direct packet type.
+/*
+ * VmbusChannelSendPacketPageBuffer - Send a range of single-page
+buffer
+ * packets using a GPADL Direct packet type.
  */
 int VmbusChannelSendPacketPageBuffer(struct vmbus_channel *Channel,
                                     struct hv_page_buffer PageBuffers[], @@ -773,8 +777,9 @@ int VmbusChannelSendPacketPageBuffer(struct vmbus_channel *Channel,
        return ret;
 }

-/**
- * VmbusChannelSendPacketMultiPageBuffer - Send a multi-page buffer packet using a GPADL Direct packet type.
+/*
+ * VmbusChannelSendPacketMultiPageBuffer - Send a multi-page buffer
+packet
+ * using a GPADL Direct packet type.
  */
 int VmbusChannelSendPacketMultiPageBuffer(struct vmbus_channel *Channel,
                                struct hv_multipage_buffer *MultiPageBuffer, @@ -842,7 +847,7 @@ int VmbusChannelSendPacketMultiPageBuffer(struct vmbus_channel *Channel,
        return ret;
 }

-/**
+/*
  * VmbusChannelRecvPacket - Retrieve the user packet on the specified channel
  */
 /* TODO: Do we ever receive a gpa direct packet other than the ones we send ? */ @@ -908,7 +913,7 @@ int VmbusChannelRecvPacket(struct vmbus_channel *Channel, void *Buffer,
        return 0;
 }

-/**
+/*
  * VmbusChannelRecvPacketRaw - Retrieve the raw packet on the specified channel
  */
 int VmbusChannelRecvPacketRaw(struct vmbus_channel *Channel, void *Buffer, @@ -971,7 +976,7 @@ int VmbusChannelRecvPacketRaw(struct vmbus_channel *Channel, void *Buffer,
        return 0;
 }

-/**
+/*
  * VmbusChannelOnChannelEvent - Channel event callback
  */
 void VmbusChannelOnChannelEvent(struct vmbus_channel *Channel) @@ -984,7 +989,7 @@ void VmbusChannelOnChannelEvent(struct vmbus_channel *Channel)
        mod_timer(&Channel->poll_timer, jiffies + usecs_to_jiffies(100));  }

-/**
+/*
  * VmbusChannelOnTimer - Timer event callback
  */
 void VmbusChannelOnTimer(unsigned long data) @@ -995,7 +1000,7 @@ void VmbusChannelOnTimer(unsigned long data)
                channel->OnChannelCallback(channel->ChannelCallbackContext);
 }

-/**
+/*
  * DumpVmbusChannel - Dump vmbus channel info to the console
  */
 static void DumpVmbusChannel(struct vmbus_channel *Channel) diff --git a/drivers/staging/hv/ChannelMgmt.c b/drivers/staging/hv/ChannelMgmt.c
index ef38467..cc4b93c 100644
--- a/drivers/staging/hv/ChannelMgmt.c
+++ b/drivers/staging/hv/ChannelMgmt.c
@@ -70,7 +70,7 @@ static const struct hv_guid
        },
 };

-/**
+/*
  * AllocVmbusChannel - Allocate and initialize a vmbus channel object
  */
 struct vmbus_channel *AllocVmbusChannel(void) @@ -96,7 +96,7 @@ struct vmbus_channel *AllocVmbusChannel(void)
        return channel;
 }

-/**
+/*
  * ReleaseVmbusChannel - Release the vmbus channel object itself
  */
 static inline void ReleaseVmbusChannel(void *context) @@ -114,7 +114,7 @@ static inline void ReleaseVmbusChannel(void *context)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * FreeVmbusChannel - Release the resources used by the vmbus channel object
  */
 void FreeVmbusChannel(struct vmbus_channel *Channel) @@ -130,7 +130,7 @@ void FreeVmbusChannel(struct vmbus_channel *Channel)
                              Channel);
 }

-/**
+/*
  * VmbusChannelProcessOffer - Process the offer by creating a channel/device associated with this offer
  */
 static void VmbusChannelProcessOffer(void *context) @@ -212,7 +212,7 @@ static void VmbusChannelProcessOffer(void *context)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelProcessRescindOffer - Rescind the offer by initiating a device removal
  */
 static void VmbusChannelProcessRescindOffer(void *context) @@ -224,7 +224,7 @@ static void VmbusChannelProcessRescindOffer(void *context)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelOnOffer - Handler for channel offers from vmbus in parent partition.
  *
  * We ignore all offers except network and storage offers. For each network and @@ -307,7 +307,7 @@ static void VmbusChannelOnOffer(struct vmbus_channel_message_header *hdr)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelOnOfferRescind - Rescind offer handler.
  *
  * We queue a work item to process this offer synchronously @@ -334,7 +334,7 @@ static void VmbusChannelOnOfferRescind(struct vmbus_channel_message_header *hdr)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelOnOffersDelivered - This is invoked when all offers have been delivered.
  *
  * Nothing to do here.
@@ -346,7 +346,7 @@ static void VmbusChannelOnOffersDelivered(
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelOnOpenResult - Open result handler.
  *
  * This is invoked when we received a response to our channel open request.
@@ -394,7 +394,7 @@ static void VmbusChannelOnOpenResult(struct vmbus_channel_message_header *hdr)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelOnGpadlCreated - GPADL created handler.
  *
  * This is invoked when we received a response to our gpadl create request.
@@ -446,7 +446,7 @@ static void VmbusChannelOnGpadlCreated(struct vmbus_channel_message_header *hdr)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelOnGpadlTorndown - GPADL torndown handler.
  *
  * This is invoked when we received a response to our gpadl teardown request.
@@ -494,7 +494,7 @@ static void VmbusChannelOnGpadlTorndown(
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelOnVersionResponse - Version response handler
  *
  * This is invoked when we received a response to our initiate contact request.
@@ -557,7 +557,7 @@ static struct vmbus_channel_message_table_entry
        {ChannelMessageUnload,                  NULL},
 };

-/**
+/*
  * VmbusOnChannelMessage - Handler for channel protocol messages.
  *
  * This is invoked in the vmbus worker thread context.
@@ -596,7 +596,7 @@ void VmbusOnChannelMessage(void *Context)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusChannelRequestOffers - Send a request to get all our pending offers.
  */
 int VmbusChannelRequestOffers(void)
@@ -650,8 +650,9 @@ Cleanup:
        return ret;
 }

-/**
- * VmbusChannelReleaseUnattachedChannels - Release channels that are unattached/unconnected ie (no drivers associated)
+/*
+ * VmbusChannelReleaseUnattachedChannels - Release channels that are
+ * unattached/unconnected ie (no drivers associated)
  */
 void VmbusChannelReleaseUnattachedChannels(void)
 {
diff --git a/drivers/staging/hv/Connection.c b/drivers/staging/hv/Connection.c index 43c2e68..894aa37 100644
--- a/drivers/staging/hv/Connection.c
+++ b/drivers/staging/hv/Connection.c
@@ -33,7 +33,7 @@ struct VMBUS_CONNECTION gVmbusConnection = {
        .NextGpadlHandle        = ATOMIC_INIT(0xE1E10),
 };

-/**
+/*
  * VmbusConnect - Sends a connect request on the partition service connection
  */
 int VmbusConnect(void)
@@ -179,7 +179,7 @@ Cleanup:
        return ret;
 }

-/**
+/*
  * VmbusDisconnect - Sends a disconnect request on the partition service connection
  */
 int VmbusDisconnect(void)
@@ -217,7 +217,7 @@ Cleanup:
        return ret;
 }

-/**
+/*
  * GetChannelFromRelId - Get the channel object given its child relative id (ie channel id)
  */
 struct vmbus_channel *GetChannelFromRelId(u32 relId) @@ -238,7 +238,7 @@ struct vmbus_channel *GetChannelFromRelId(u32 relId)
        return foundChannel;
 }

-/**
+/*
  * VmbusProcessChannelEvent - Process a channel event notification
  */
 static void VmbusProcessChannelEvent(void *context) @@ -266,7 +266,7 @@ static void VmbusProcessChannelEvent(void *context)
        }
 }

-/**
+/*
  * VmbusOnEvents - Handler for events
  */
 void VmbusOnEvents(void)
@@ -307,7 +307,7 @@ void VmbusOnEvents(void)
        return;
 }

-/**
+/*
  * VmbusPostMessage - Send a msg on the vmbus's message connection
  */
 int VmbusPostMessage(void *buffer, size_t bufferLen) @@ -319,7 +319,7 @@ int VmbusPostMessage(void *buffer, size_t bufferLen)
        return HvPostMessage(connId, 1, buffer, bufferLen);  }

-/**
+/*
  * VmbusSetEvent - Send an event notification to the parent
  */
 int VmbusSetEvent(u32 childRelId)
diff --git a/drivers/staging/hv/Hv.c b/drivers/staging/hv/Hv.c index 51149e6..9bee568 100644
--- a/drivers/staging/hv/Hv.c
+++ b/drivers/staging/hv/Hv.c
@@ -34,7 +34,7 @@ struct hv_context gHvContext = {
        .SignalEventBuffer      = NULL,
 };

-/**
+/*
  * HvQueryHypervisorPresence - Query the cpuid for presense of windows hypervisor
  */
 static int HvQueryHypervisorPresence(void) @@ -55,7 +55,7 @@ static int HvQueryHypervisorPresence(void)
        return ecx & HV_PRESENT_BIT;
 }

-/**
+/*
  * HvQueryHypervisorInfo - Get version info of the windows hypervisor
  */
 static int HvQueryHypervisorInfo(void)
@@ -124,7 +124,7 @@ static int HvQueryHypervisorInfo(void)
        return maxLeaf;
 }

-/**
+/*
  * HvDoHypercall - Invoke the specified hypercall
  */
 static u64 HvDoHypercall(u64 Control, void *Input, void *Output) @@ -179,7 +179,7 @@ static u64 HvDoHypercall(u64 Control, void *Input, void *Output)  #endif /* !x86_64 */  }

-/**
+/*
  * HvInit - Main initialization routine.
  *
  * This routine must be called before any other routines in here are called @@ -293,7 +293,7 @@ Cleanup:
        return ret;
 }

-/**
+/*
  * HvCleanup - Cleanup routine.
  *
  * This routine is called normally during driver unloading or exiting.
@@ -320,7 +320,7 @@ void HvCleanup(void)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * HvPostMessage - Post a message using the hypervisor message IPC.
  *
  * This involves a hypercall.
@@ -361,7 +361,7 @@ u16 HvPostMessage(union hv_connection_id connectionId,  }


-/**
+/*
  * HvSignalEvent - Signal an event on the specified connection using the hypervisor event IPC.
  *
  * This involves a hypercall.
@@ -375,7 +375,7 @@ u16 HvSignalEvent(void)
        return status;
 }

-/**
+/*
  * HvSynicInit - Initialize the Synthethic Interrupt Controller.
  *
  * If it is already initialized by another entity (ie x2v shim), we need to @@ -481,7 +481,7 @@ Cleanup:
        return;
 }

-/**
+/*
  * HvSynicCleanup - Cleanup routine for HvSynicInit().
  */
 void HvSynicCleanup(void *arg)
diff --git a/drivers/staging/hv/NetVsc.c b/drivers/staging/hv/NetVsc.c index 1c717f9..bd739ac 100644
--- a/drivers/staging/hv/NetVsc.c
+++ b/drivers/staging/hv/NetVsc.c
@@ -166,7 +166,7 @@ static struct netvsc_device *ReleaseInboundNetDevice(struct hv_device *Device)
        return netDevice;
 }

-/**
+/*
  * NetVscInitialize - Main entry point
  */
 int NetVscInitialize(struct hv_driver *drv) @@ -704,7 +704,7 @@ static void NetVscDisconnectFromVsp(struct netvsc_device *NetDevice)
        DPRINT_EXIT(NETVSC);
 }

-/**
+/*
  * NetVscOnDeviceAdd - Callback when the device belonging to this driver is added
  */
 static int NetVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo) @@ -806,7 +806,7 @@ Cleanup:
        return ret;
 }

-/**
+/*
  * NetVscOnDeviceRemove - Callback when the root bus device is removed
  */
 static int NetVscOnDeviceRemove(struct hv_device *Device) @@ -863,7 +863,7 @@ static int NetVscOnDeviceRemove(struct hv_device *Device)
        return 0;
 }

-/**
+/*
  * NetVscOnCleanup - Perform any cleanup when the driver is removed
  */
 static void NetVscOnCleanup(struct hv_driver *drv) diff --git a/drivers/staging/hv/StorVsc.c b/drivers/staging/hv/StorVsc.c index 38ea140..5a09d08 100644
--- a/drivers/staging/hv/StorVsc.c
+++ b/drivers/staging/hv/StorVsc.c
@@ -532,7 +532,7 @@ static int StorVscConnectToVsp(struct hv_device *Device)
        return ret;
 }

-/**
+/*
  * StorVscOnDeviceAdd - Callback when the device belonging to this driver is added
  */
 static int StorVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo) @@ -584,7 +584,7 @@ Cleanup:
        return ret;
 }

-/**
+/*
  * StorVscOnDeviceRemove - Callback when the our device is being removed
  */
 static int StorVscOnDeviceRemove(struct hv_device *Device) @@ -682,7 +682,7 @@ Cleanup:
        return ret;
 }

-/**
+/*
  * StorVscOnIORequest - Callback to initiate an I/O request
  */
 static int StorVscOnIORequest(struct hv_device *Device, @@ -782,7 +782,7 @@ static int StorVscOnIORequest(struct hv_device *Device,
        return ret;
 }

-/**
+/*
  * StorVscOnCleanup - Perform any cleanup when the driver is removed
  */
 static void StorVscOnCleanup(struct hv_driver *Driver) @@ -791,7 +791,7 @@ static void StorVscOnCleanup(struct hv_driver *Driver)
        DPRINT_EXIT(STORVSC);
 }

-/**
+/*
  * StorVscInitialize - Main entry point
  */
 int StorVscInitialize(struct hv_driver *Driver) diff --git a/drivers/staging/hv/TODO b/drivers/staging/hv/TODO index dbfbde9..78d957e 100644
--- a/drivers/staging/hv/TODO
+++ b/drivers/staging/hv/TODO
@@ -1,6 +1,5 @@
 TODO:
        - fix remaining checkpatch warnings and errors
-       - use of /** when it is not a kerneldoc header
        - remove RingBuffer.c to us in-kernel ringbuffer functions instead.
        - audit the vmbus to verify it is working properly with the
          driver model
diff --git a/drivers/staging/hv/Vmbus.c b/drivers/staging/hv/Vmbus.c index 3d0a240..9a6a340 100644
--- a/drivers/staging/hv/Vmbus.c
+++ b/drivers/staging/hv/Vmbus.c
@@ -51,7 +51,7 @@ static const struct hv_guid gVmbusDeviceId = {  static struct hv_driver *gDriver; /* vmbus driver object */  static struct hv_device *gDevice; /* vmbus root device */

-/**
+/*
  * VmbusGetChannelOffers - Retrieve the channel offers from the parent partition
  */
 static void VmbusGetChannelOffers(void) @@ -61,7 +61,7 @@ static void VmbusGetChannelOffers(void)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusGetChannelInterface - Get the channel interface
  */
 static void VmbusGetChannelInterface(struct vmbus_channel_interface *Interface) @@ -69,7 +69,7 @@ static void VmbusGetChannelInterface(struct vmbus_channel_interface *Interface)
        GetChannelInterface(Interface);
 }

-/**
+/*
  * VmbusGetChannelInfo - Get the device info for the specified device object
  */
 static void VmbusGetChannelInfo(struct hv_device *DeviceObject, @@ -78,7 +78,7 @@ static void VmbusGetChannelInfo(struct hv_device *DeviceObject,
        GetChannelInfo(DeviceObject, DeviceInfo);  }

-/**
+/*
  * VmbusCreateChildDevice - Creates the child device on the bus that represents the channel offer
  */
 struct hv_device *VmbusChildDeviceCreate(struct hv_guid *DeviceType, @@ -91,7 +91,7 @@ struct hv_device *VmbusChildDeviceCreate(struct hv_guid *DeviceType,
                                                Context);
 }

-/**
+/*
  * VmbusChildDeviceAdd - Registers the child device with the vmbus
  */
 int VmbusChildDeviceAdd(struct hv_device *ChildDevice) @@ -101,7 +101,7 @@ int VmbusChildDeviceAdd(struct hv_device *ChildDevice)
        return vmbusDriver->OnChildDeviceAdd(gDevice, ChildDevice);  }

-/**
+/*
  * VmbusChildDeviceRemove Unregisters the child device from the vmbus
  */
 void VmbusChildDeviceRemove(struct hv_device *ChildDevice) @@ -111,7 +111,7 @@ void VmbusChildDeviceRemove(struct hv_device *ChildDevice)
        vmbusDriver->OnChildDeviceRemove(ChildDevice);
 }

-/**
+/*
  * VmbusOnDeviceAdd - Callback when the root bus device is added
  */
 static int VmbusOnDeviceAdd(struct hv_device *dev, void *AdditionalInfo) @@ -140,7 +140,7 @@ static int VmbusOnDeviceAdd(struct hv_device *dev, void *AdditionalInfo)
        return ret;
 }

-/**
+/*
  * VmbusOnDeviceRemove - Callback when the root bus device is removed
  */
 static int VmbusOnDeviceRemove(struct hv_device *dev) @@ -156,7 +156,7 @@ static int VmbusOnDeviceRemove(struct hv_device *dev)
        return ret;
 }

-/**
+/*
  * VmbusOnCleanup - Perform any cleanup when the driver is removed
  */
 static void VmbusOnCleanup(struct hv_driver *drv) @@ -168,7 +168,7 @@ static void VmbusOnCleanup(struct hv_driver *drv)
        DPRINT_EXIT(VMBUS);
 }

-/**
+/*
  * VmbusOnMsgDPC - DPC routine to handle messages from the hypervisior
  */
 static void VmbusOnMsgDPC(struct hv_driver *drv) @@ -216,7 +216,7 @@ static void VmbusOnMsgDPC(struct hv_driver *drv)
        }
 }

-/**
+/*
  * VmbusOnEventDPC - DPC routine to handle events from the hypervisior
  */
 static void VmbusOnEventDPC(struct hv_driver *drv) @@ -225,7 +225,7 @@ static void VmbusOnEventDPC(struct hv_driver *drv)
        VmbusOnEvents();
 }

-/**
+/*
  * VmbusOnISR - ISR routine
  */
 static int VmbusOnISR(struct hv_driver *drv) @@ -263,7 +263,7 @@ static int VmbusOnISR(struct hv_driver *drv)
        return ret;
 }

-/**
+/*
  * VmbusInitialize - Main entry point
  */
 int VmbusInitialize(struct hv_driver *drv) diff --git a/drivers/staging/hv/VmbusApi.h b/drivers/staging/hv/VmbusApi.h index d089bb1..2e3a3b8 100644
--- a/drivers/staging/hv/VmbusApi.h
+++ b/drivers/staging/hv/VmbusApi.h
@@ -84,6 +84,25 @@ struct hv_device_info {
        struct hv_dev_port_info Outbound;
 };

+/**
+ * struct vmbus_channel_interface - Contains member functions for vmbus channel
+ * @Open:      Open the channel
+ * @Close:     Close the channel
+ * @SendPacket:        Send a packet over the channel
+ * @SendPacketPageBuffer:      Send a single page buffer over the channel
+ * @SendPacketMultiPageBuffer: Send a multiple page buffers
+ * @RecvPacket:        Receive packet
+ * @RecvPacketRaw:     Receive Raw packet
+ * @EstablishGpadl:    Set up GPADL for ringbuffer
+ * @TeardownGpadl:     Teardown GPADL for ringbuffer
+ * @GetInfo:   Get info about the channel
+ *
+ * This structure contains function pointer to control vmbus channel
+ * behavior.
+ * None of these functions is externally callable, but they are used
+for normal
+ * vmbus channel internal behavior.
+ * Only used by Hyper-V drivers.
+ */
 struct vmbus_channel_interface {
        int (*Open)(struct hv_device *Device, u32 SendBufferSize,
                    u32 RecvRingBufferSize, void *UserData, u32 UserDataLen, diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index abeac12..c90a6aa 100644
--- a/drivers/staging/hv/blkvsc_drv.c
+++ b/drivers/staging/hv/blkvsc_drv.c
@@ -164,7 +164,7 @@ static struct block_device_operations block_ops = {
        .ioctl  = blkvsc_ioctl,
 };

-/**
+/*
  * blkvsc_drv_init -  BlkVsc driver initialization.
  */
 static int blkvsc_drv_init(int (*drv_init)(struct hv_driver *drv)) @@ -244,7 +244,7 @@ static void blkvsc_drv_exit(void)
        return;
 }

-/**
+/*
  * blkvsc_probe - Add a new device for this driver
  */
 static int blkvsc_probe(struct device *device) @@ -732,7 +732,7 @@ static int blkvsc_do_read_capacity16(struct block_device_context *blkdev)
        return 0;
 }

-/**
+/*
  * blkvsc_remove() - Callback when our device is removed
  */
 static int blkvsc_remove(struct device *device) diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 1af3dcb..933597e 100644
--- a/drivers/staging/hv/netvsc_drv.c
+++ b/drivers/staging/hv/netvsc_drv.c
@@ -265,7 +265,7 @@ retry_send:
        return ret;
 }

-/**
+/*
  * netvsc_linkstatus_callback - Link up/down notification
  */
 static void netvsc_linkstatus_callback(struct hv_device *device_obj, @@ -292,7 +292,7 @@ static void netvsc_linkstatus_callback(struct hv_device *device_obj,
        DPRINT_EXIT(NETVSC_DRV);
 }

-/**
+/*
  * netvsc_recv_callback -  Callback when we receive a packet from the "wire" on the specified device.
  */
 static int netvsc_recv_callback(struct hv_device *device_obj, diff --git a/drivers/staging/hv/osd.c b/drivers/staging/hv/osd.c index 3a4793a..5afa94e 100644
--- a/drivers/staging/hv/osd.c
+++ b/drivers/staging/hv/osd.c
@@ -58,6 +58,15 @@ void *osd_VirtualAllocExec(unsigned int size)  #endif  }

+/**
+ * osd_PageAlloc() - Allocate pages
+ * @count:      Total number of Kernel pages you want to allocate
+ *
+ * Tries to allocate @count number of consecutive free kernel pages.
+ * And if successful, it will set the pages to 0 before returning.
+ * If successfull it will return pointer to the @count pages.
+ * Mainly used by Hyper-V drivers.
+ */
 void *osd_PageAlloc(unsigned int count)  {
        void *p;
@@ -77,6 +86,14 @@ void *osd_PageAlloc(unsigned int count)  }  EXPORT_SYMBOL_GPL(osd_PageAlloc);

+/**
+ * osd_PageFree() - Free pages
+ * @page:       Pointer to the first page to be freed
+ * @count:      Total number of Kernel pages you free
+ *
+ * Frees the pages allocated by osd_PageAlloc()
+ * Mainly used by Hyper-V drivers.
+ */
 void osd_PageFree(void *page, unsigned int count)  {
        free_pages((unsigned long)page, get_order(count * PAGE_SIZE)); @@ -85,6 +102,17 @@ void osd_PageFree(void *page, unsigned int count)  }  EXPORT_SYMBOL_GPL(osd_PageFree);

+/**
+ * osd_WaitEventCreate() - Create the event queue
+ *
+ * Allocates memory for a &struct osd_waitevent. And than calls
+ * init_waitqueue_head to set up the wait queue for the event.
+ * This structure is usually part of a another structure that contains
+ * the actual Hyper-V device driver structure.
+ *
+ * Returns pointer to &struct osd_waitevent
+ * Mainly used by Hyper-V drivers.
+ */
 struct osd_waitevent *osd_WaitEventCreate(void)  {
        struct osd_waitevent *wait = kmalloc(sizeof(struct osd_waitevent), @@ -98,6 +126,19 @@ struct osd_waitevent *osd_WaitEventCreate(void)  }  EXPORT_SYMBOL_GPL(osd_WaitEventCreate);

+
+/**
+ * osd_WaitEventSet() - Wake up the process
+ * @waitEvent: Structure to event to be woken up
+ *
+ * @waitevent is of type @struct osd_waitevent
+ *
+ * Wake up the sleeping process so it can do some work.
+ * And set condition indicator in struct osd_waitevent to indicate
+ * the process is in a woken state.
+ *
+ * Only used by Network and Storage Hyper-V drivers.
+ */
 void osd_WaitEventSet(struct osd_waitevent *waitEvent)  {
        waitEvent->condition = 1;
@@ -105,6 +146,20 @@ void osd_WaitEventSet(struct osd_waitevent *waitEvent)  }  EXPORT_SYMBOL_GPL(osd_WaitEventSet);

+/**
+ * osd_WaitEventWait() - Wait for event till condition is true
+ * @waitEvent: Structure to event to be put to sleep
+ *
+ * @waitevent is of type @struct osd_waitevent
+ *
+ * Set up the process to sleep until waitEvent->condition get true.
+ * And set condition indicator in struct osd_waitevent to indicate
+ * the process is in a sleeping state.
+ *
+ * Returns the status of 'wait_event_interruptible()' system call
+ *
+ * Mainly used by Hyper-V drivers.
+ */
 int osd_WaitEventWait(struct osd_waitevent *waitEvent)  {
        int ret = 0;
@@ -116,6 +171,21 @@ int osd_WaitEventWait(struct osd_waitevent *waitEvent)  }  EXPORT_SYMBOL_GPL(osd_WaitEventWait);

+/**
+ * osd_WaitEventWaitEx() - Wait for event or timeout for process wakeup
+ * @waitEvent: Structure to event to be put to sleep
+ * @TimeoutInMs:       Total number of Milliseconds to wait before waking up
+ *
+ * @waitevent is of type @struct osd_waitevent
+ * Set up the process to sleep until @waitEvent->condition get true or
+ * @TimeoutInMs (Time out in Milliseconds) has been reached.
+ * And set condition indicator in struct osd_waitevent to indicate
+ * the process is in a sleeping state.
+ *
+ * Returns the status of 'wait_event_interruptible_timeout()' system
+call
+ *
+ * Mainly used by Hyper-V drivers.
+ */
 int osd_WaitEventWaitEx(struct osd_waitevent *waitEvent, u32 TimeoutInMs)  {
        int ret = 0;
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 3988f4b..7676ba5 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -129,7 +129,7 @@ static struct scsi_host_template scsi_driver = {  };


-/**
+/*
  * storvsc_drv_init - StorVsc driver initialization.
  */
 static int storvsc_drv_init(int (*drv_init)(struct hv_driver *drv)) @@ -222,7 +222,7 @@ static void storvsc_drv_exit(void)
        return;
 }

-/**
+/*
  * storvsc_probe - Add a new device for this driver
  */
 static int storvsc_probe(struct device *device) @@ -318,7 +318,7 @@ static int storvsc_probe(struct device *device)
        return ret;
 }

-/**
+/*
  * storvsc_remove - Callback when our device is removed
  */
 static int storvsc_remove(struct device *device) @@ -371,7 +371,7 @@ static int storvsc_remove(struct device *device)
        return ret;
 }

-/**
+/*
  * storvsc_commmand_completion - Command completion processing
  */
 static void storvsc_commmand_completion(struct hv_storvsc_request *request) @@ -622,7 +622,7 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
        return total_copied;
 }

-/**
+/*
  * storvsc_queuecommand - Initiate command processing
  */
 static int storvsc_queuecommand(struct scsi_cmnd *scmnd, @@ -823,7 +823,7 @@ static int storvsc_merge_bvec(struct request_queue *q,
        return bvec->bv_len;
 }

-/**
+/*
  * storvsc_device_configure - Configure the specified scsi device
  */
 static int storvsc_device_alloc(struct scsi_device *sdevice) @@ -862,7 +862,7 @@ static int storvsc_device_configure(struct scsi_device *sdevice)
        return 0;
 }

-/**
+/*
  * storvsc_host_reset_handler - Reset the scsi HBA
  */
 static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index 2c90619..177f565 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/staging/hv/vmbus_drv.c
@@ -128,7 +128,7 @@ static struct vmbus_driver_context g_vmbus_drv = {
        .bus.dev_attrs =        vmbus_device_attrs,
 };

-/**
+/*
  * vmbus_show_device_attr - Show the device attribute in sysfs.
  *
  * This is invoked when user does a
@@ -232,7 +232,7 @@ static ssize_t vmbus_show_device_attr(struct device *dev,
        }
 }

-/**
+/*
  * vmbus_bus_init -Main vmbus driver initialization routine.
  *
  * Here, we
@@ -361,7 +361,7 @@ cleanup:
        return ret;
 }

-/**
+/*
  * vmbus_bus_exit - Terminate the vmbus driver.
  *
  * This routine is opposite of vmbus_bus_init() @@ -397,8 +397,18 @@ static void vmbus_bus_exit(void)
        return;
 }

+
 /**
- * vmbus_child_driver_register - Register a vmbus's child driver
+ * vmbus_child_driver_register() - Register a vmbus's child driver
+ * @driver_ctx:        Pointer to driver structure you want to register
+ *
+ * @driver_ctx is of type &struct driver_context
+ *
+ * Registers the given driver with Linux through the
+ 'driver_register()' call
+ * And sets up the hyper-v vmbus handling for this driver.
+ * It will return the state of the 'driver_register()' call.
+ *
+ * Mainly used by Hyper-V drivers.
  */
 int vmbus_child_driver_register(struct driver_context *driver_ctx)  { @@ -424,7 +434,15 @@ int vmbus_child_driver_register(struct driver_context *driver_ctx)  EXPORT_SYMBOL(vmbus_child_driver_register);

 /**
- * vmbus_child_driver_unregister Unregister a vmbus's child driver
+ * vmbus_child_driver_unregister() - Unregister a vmbus's child driver
+ * @driver_ctx:        Pointer to driver structure you want to un-register
+ *
+ * @driver_ctx is of type &struct driver_context
+ *
+ * Un-register the given driver with Linux through the 'driver_unregister()'
+ * call. And ungegisters the driver from the Hyper-V vmbus handler.
+ *
+ * Mainly used by Hyper-V drivers.
  */
 void vmbus_child_driver_unregister(struct driver_context *driver_ctx)  { @@ -442,9 +460,15 @@ void vmbus_child_driver_unregister(struct driver_context *driver_ctx)  EXPORT_SYMBOL(vmbus_child_driver_unregister);

 /**
- * vmbus_get_interface - Get the vmbus channel interface.
+ * vmbus_get_interface() - Get the vmbus channel interface.
+ * @interface: Pointer to channel interface structure
+ *
+ * Get the Hyper-V channel used for the driver.
+ *
+ * @interface is of type &struct vmbus_channel_interface
+ * This is invoked by child/client driver that sits above vmbus.
  *
- * This is invoked by child/client driver that sits above vmbus
+ * Mainly used by Hyper-V drivers.
  */
 void vmbus_get_interface(struct vmbus_channel_interface *interface)  { @@ -454,7 +478,7 @@ void vmbus_get_interface(struct vmbus_channel_interface *interface)  }  EXPORT_SYMBOL(vmbus_get_interface);

-/**
+/*
  * vmbus_child_device_get_info - Get the vmbus child device info.
  *
  * This is invoked to display various device attributes in sysfs.
@@ -467,8 +491,9 @@ static void vmbus_child_device_get_info(struct hv_device *device_obj,
        vmbus_drv_obj->GetChannelInfo(device_obj, device_info);  }

-/**
- * vmbus_child_device_create - Creates and registers a new child device on the vmbus.
+/*
+ * vmbus_child_device_create - Creates and registers a new child device
+ * on the vmbus.
  */
 static struct hv_device *vmbus_child_device_create(struct hv_guid *type,
                                                   struct hv_guid *instance,
@@ -522,7 +547,7 @@ static struct hv_device *vmbus_child_device_create(struct hv_guid *type,
        return child_device_obj;
 }

-/**
+/*
  * vmbus_child_device_register - Register the child device on the specified bus
  */
 static int vmbus_child_device_register(struct hv_device *root_device_obj, @@ -570,8 +595,9 @@ static int vmbus_child_device_register(struct hv_device *root_device_obj,
        return ret;
 }

-/**
- * vmbus_child_device_unregister - Remove the specified child device from the vmbus.
+/*
+ * vmbus_child_device_unregister - Remove the specified child device
+ * from the vmbus.
  */
 static void vmbus_child_device_unregister(struct hv_device *device_obj)  { @@ -594,7 +620,7 @@ static void vmbus_child_device_unregister(struct hv_device *device_obj)
        DPRINT_EXIT(VMBUS_DRV);
 }

-/**
+/*
  * vmbus_child_device_destroy - Destroy the specified child device on the vmbus.
  */
 static void vmbus_child_device_destroy(struct hv_device *device_obj) @@ -604,7 +630,7 @@ static void vmbus_child_device_destroy(struct hv_device *device_obj)
        DPRINT_EXIT(VMBUS_DRV);
 }

-/**
+/*
  * vmbus_uevent - add uevent for our device
  *
  * This routine is invoked when a device is added or removed on the vmbus to @@ -683,7 +709,7 @@ static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
        return 0;
 }

-/**
+/*
  * vmbus_match - Attempt to match the specified device to the specified driver
  */
 static int vmbus_match(struct device *device, struct device_driver *driver) @@ -718,7 +744,7 @@ static int vmbus_match(struct device *device, struct device_driver *driver)
        return match;
 }

-/**
+/*
  * vmbus_probe_failed_cb - Callback when a driver probe failed in vmbus_probe()
  *
  * We need a callback because we cannot invoked device_unregister() inside @@ -741,7 +767,7 @@ static void vmbus_probe_failed_cb(struct work_struct *context)
        DPRINT_EXIT(VMBUS_DRV);
 }

-/**
+/*
  * vmbus_probe - Add the new vmbus's child device
  */
 static int vmbus_probe(struct device *child_device) @@ -777,7 +803,7 @@ static int vmbus_probe(struct device *child_device)
        return ret;
 }

-/**
+/*
  * vmbus_remove - Remove a vmbus device
  */
 static int vmbus_remove(struct device *child_device) @@ -819,7 +845,7 @@ static int vmbus_remove(struct device *child_device)
        return 0;
 }

-/**
+/*
  * vmbus_shutdown - Shutdown a vmbus device
  */
 static void vmbus_shutdown(struct device *child_device) @@ -855,7 +881,7 @@ static void vmbus_shutdown(struct device *child_device)
        return;
 }

-/**
+/*
  * vmbus_bus_release - Final callback release of the vmbus root device
  */
 static void vmbus_bus_release(struct device *device) @@ -869,7 +895,7 @@ static void vmbus_bus_release(struct device *device)
        DPRINT_EXIT(VMBUS_DRV);
 }

-/**
+/*
  * vmbus_device_release - Final callback release of the vmbus child device
  */
 static void vmbus_device_release(struct device *device) @@ -887,7 +913,7 @@ static void vmbus_device_release(struct device *device)
        return;
 }

-/**
+/*
  * vmbus_msg_dpc - Tasklet routine to handle hypervisor messages
  */
 static void vmbus_msg_dpc(unsigned long data) @@ -904,7 +930,7 @@ static void vmbus_msg_dpc(unsigned long data)
        DPRINT_EXIT(VMBUS_DRV);
 }

-/**
+/*
  * vmbus_msg_dpc - Tasklet routine to handle hypervisor events
  */
 static void vmbus_event_dpc(unsigned long data)

^ permalink raw reply related

* [PATCH 1/1] Stage: hv: Remove Ringbuffer from TODO line
From: Hank Janssen @ 2010-03-04 17:46 UTC (permalink / raw)
  To: 'linux-kernel@vger.kernel.org',
	devel@driverdev.osuosl.org, virtualization@lists.osdl.org
  Cc: Haiyang Zhang, Hashir Abdi, Greg KH
In-Reply-To: <1FB5E1D5CA062146B38059374562DF725A908A11@TK5EX14MBXC126.redmond.corp.microsoft.com>

From: Hank Janssen <hjanssen@microsoft.com>

Remove Ringbuffer work line item from TODO file. 

The ring buffer in the Hyper-V Linux drivers is used to communicate with 
the parent partition running Windows Server 2008 Hyper-V. The ring buffer functionality 
on the Hyper-V Linux drivers is written to be functionally compatible with 
the ring buffer functionality on the Hyper-V Server. Consequently, it is not 
possible to make any changes that might break the compatibility with server 
side ring buffer implementation.

Cc: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>

---
 drivers/staging/hv/TODO |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/hv/TODO b/drivers/staging/hv/TODO index dbfbde9..efe8ce9 100644
--- a/drivers/staging/hv/TODO
+++ b/drivers/staging/hv/TODO
@@ -1,7 +1,6 @@
 TODO:
 	- fix remaining checkpatch warnings and errors
 	- use of /** when it is not a kerneldoc header
-	- remove RingBuffer.c to us in-kernel ringbuffer functions instead.
 	- audit the vmbus to verify it is working properly with the
 	  driver model
 	- convert vmbus driver interface function pointer tables

^ permalink raw reply

* Re: virtio over PCI
From: Ira W. Snyder @ 2010-03-04  0:39 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: Grant Likely, Arnd Bergmann, virtualization
In-Reply-To: <1267596588.7814.159.camel@concordia>

On Wed, Mar 03, 2010 at 05:09:48PM +1100, Michael Ellerman wrote:
> Hi guys,
> 
> I was looking around at virtio over PCI stuff and noticed you had
> started some work on a driver. The last I can find via google is v2 from
> mid last year, is that as far as it got?
> 
> http://lkml.org/lkml/2009/2/23/353
> 

Yep, that is pretty much as far as I got. It was more-or-less rejected
because I hooked two instances of virtio-net together, rather than
having a proper backend and using virtio-net as the frontend.

I got started on writing a backend, which was never posted to LKML
because I never finished it. Feel free to take the code and use it to
start your own project. Note that vhost-net exists now, and is an
in-kernel backend for virtio-net. It *may* be possible to use this,
rather than writing a userspace backend as I started to do.
http://www.mmarray.org/~iws/virtio-phys/

I also got started with the alacrityvm project, developing a driver for
their virtualization framework. That project is nowhere near finished.
The virtualization folks basically told GHaskins (alacrityvm author)
that alacrityvm wouldn't ever make it to mainline Linux.
http://www.mmarray.org/~iws/vbus/

Unfortunately, I've been pulled onto other projects for the time being.
However, I'd really like to be able to use a virtio-over-PCI style
driver, rather than relying on my own custom (slow, unoptimized) network
driver (PCINet).

If you get something mostly working (and mostly agreed upon by the
virtualization guys), I will make the time to test it and get it cleaned
up. I've had 10+ people email me privately about this kind of driver
now. It is an area where Linux is sorely lacking.

I'm happy to provide any help I can, including testing on
MPC8349EA-based system. I would suggest talking to the virtualization
mailing list before you get too deep in the project. They sometimes have
good advice. I've added them to the CC list, so maybe they can comment.
https://lists.linux-foundation.org/mailman/listinfo/virtualization

Good luck, and let me know if I can help.
Ira

^ permalink raw reply

* Re: Ringbuffer usage in Linux Hyper-V drivers
From: Greg KH @ 2010-03-03 23:39 UTC (permalink / raw)
  To: Hank Janssen
  Cc: 'linux-kernel@vger.kernel.org',
	devel@driverdev.osuosl.org, virtualization@lists.osdl.org,
	Haiyang Zhang, Hashir Abdi
In-Reply-To: <8AFC7968D54FB448A30D8F38F259C56212EE39C0@TK5EX14MBXC116.redmond.corp.microsoft.com>

On Wed, Mar 03, 2010 at 04:42:27PM +0000, Hank Janssen wrote:
> The ring buffer in the Hyper-V Linux drivers is used to communicate with the 
> parent partition running Server 2008 Hyper-V. The ring buffer functionality on 
> the Hyper-V Linux drivers is written to be functionally compatible with" the 
> ring buffer functionality on the Hyper-V Server. Consequently, it is not 
> possible to make any changes that might break the compatibility with server 
> side ring buffer implementation.  

Ok, that makes sense, feel free to remove that TODO item.

thanks for looking into this.

greg k-h

^ permalink raw reply

* Re: Ringbuffer usage in Linux Hyper-V drivers
From: Jeremy Fitzhardinge @ 2010-03-03 17:49 UTC (permalink / raw)
  To: Hank Janssen
  Cc: 'linux-kernel@vger.kernel.org',
	devel@driverdev.osuosl.org, virtualization@lists.osdl.org,
	Haiyang Zhang, Hashir Abdi
In-Reply-To: <8AFC7968D54FB448A30D8F38F259C56212EE39C0@TK5EX14MBXC116.redmond.corp.microsoft.com>

On 03/03/2010 08:42 AM, Hank Janssen wrote:
> There is a pretty good chance that ring buffer on Hyper-V will change to support
> additional functionality. I did further investigations to check on other
> virtualization technologies. And this same things seems to be true for XEN,
> they also implemented their own ring buffer implementation on the guest side
> because of their host side implementation.
>    

Yes.  The cross-domain producer-consumer ringbuffer is a pretty specific 
protocol.  Not only is the data format an ABI, but the exact protocol 
for what pointers get updated when, etc.  Its not at all obvious how we 
could reuse the kernel ringbuffer implementation, since it assumes its 
implementing both the producer and consumer ends.

> So my question is to the community at large, am I missing something that would
> enable me to use an existing ring buffer functionality somehow in the kernel?
> If not, I want to remove the line from the TODO file that is requesting to use the
> in-kernel ring buffer functionality.
>
> Finally, while checking this out, I looked at a bunch of non virtualization device
> drivers currently in the kernel. And all the ones I looked at have
> implemented their own ring buffer. Is there a reason why this might be the case?
>    

linux/ring_buffer.h is relatively new, and probably post-dates most of 
the driver ringbuffers.  If the ringbuffer is entirely within the kernel 
(say, between an ISR and the rest of the kernel) then I guess it might 
be possible to use the standard functions.  But if half the ringbuffer 
is being managed by the device itself, then that will define the protocol.

     J

^ permalink raw reply

* Re: [RFC][ PATCH 0/3] vhost-net: Add mergeable RX buffer support to vhost-net
From: David Stevens @ 2010-03-03 17:28 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: kvm, netdev, netdev-owner, rusty, virtualization
In-Reply-To: <20100303092850.GB14034@redhat.com>

> Interesting. Since the feature in question is billed first of all a
> performance optimization...

By whom? Although I see some improved performance, I think its real
benefit is improving memory utilization on the guest. Instead of using
75K for an ARP packet, mergeable RX buffers only uses 4K. :-)

> Since the patches affect code paths when mergeable RX buffers are
> disabled as well, I guess the most important point would be to verify
> whether there's increase in latency and/or CPU utilization, or bandwidth
> cost when the feature bit is *disabled*.

Actually, when the feature bit is disabled, it'll only get a single
head, doesn't use the special vnet_hdr, and the codepath reduces to the
essentially to the original. But the answer is "no"; I saw no regressions
when using it without the feature bit. The only substantive difference in 
that case
is that the new code avoids copying the vnet header as the original
does, so it should actually be faster, but I don't think that's measurable
above the variability I already see.

> 
> > 2 notes: I have a modified version of qemu to get the VHOST_FEATURES
> > flags, including the mergeable RX bufs flag, passed to the guest; I'll
> > be working with your current qemu git trees next, if any changes are
> > needed to support it there.
> 
> This feature also seems to conflict with zero-copy rx patches from Xin
> Xiaohui (subject: Provide a zero-copy method on KVM virtio-net) these
> are not in a mergeable shape yet, so this is not a blocker, but I wonder
> what your thoughts on the subject are: how will we do feature
> negotiation if some backends don't support some features?

        The qemu code I have basically sends the set features and get
features all the way to vhost (ie, it's the guest negotiating with
vhost), except, of course, for the magic qemu-only bits. I think that's
the right model. I'll definitely take a look at the patch you mention
and maybe comment further.

                                                                +-DLS


^ permalink raw reply

* Re: virtio over PCI
From: Arnd Bergmann @ 2010-03-03 16:45 UTC (permalink / raw)
  To: Ira W. Snyder
  Cc: Michael Ellerman, Grant Likely, Mark Purcell, virtualization
In-Reply-To: <20100304003920.GA12707@ovro.caltech.edu>

On Thursday 04 March 2010, Ira W. Snyder wrote:

> I'm happy to provide any help I can, including testing on
> MPC8349EA-based system. I would suggest talking to the virtualization
> mailing list before you get too deep in the project. They sometimes have
> good advice. I've added them to the CC list, so maybe they can comment.
> https://lists.linux-foundation.org/mailman/listinfo/virtualization

You may also want to get together with Mark Purcell (if you are not
already working with him). He may be working on the same hardware that
you are interested in, just guessing ;-).

	Arnd

^ permalink raw reply

* Ringbuffer usage in Linux Hyper-V drivers
From: Hank Janssen @ 2010-03-03 16:42 UTC (permalink / raw)
  To: 'linux-kernel@vger.kernel.org',
	devel@driverdev.osuosl.org, virtualization@lists.osdl.org
  Cc: Haiyang Zhang, Hashir Abdi
In-Reply-To: <20100217235223.GG12197@kroah.com>



All,

I have been looking at one of the TODO items in the Linux Hyper-V drivers. 

Specifically the one that says;

	- remove RingBuffer.c to use in-kernel ringbuffer functions instead.

I spend some time figuring out the ring buffer capability inside of the Linux 
Kernel to see if we could change the Hyper-V ring buffer out for the in-kernel 
ring buffer capability.

The ring buffer in the Hyper-V Linux drivers is used to communicate with the 
parent partition running Server 2008 Hyper-V. The ring buffer functionality on 
the Hyper-V Linux drivers is written to be functionally compatible with" the 
ring buffer functionality on the Hyper-V Server. Consequently, it is not 
possible to make any changes that might break the compatibility with server 
side ring buffer implementation.  

There is a pretty good chance that ring buffer on Hyper-V will change to support 
additional functionality. I did further investigations to check on other 
virtualization technologies. And this same things seems to be true for XEN, 
they also implemented their own ring buffer implementation on the guest side 
because of their host side implementation.

So my question is to the community at large, am I missing something that would 
enable me to use an existing ring buffer functionality somehow in the kernel?  
If not, I want to remove the line from the TODO file that is requesting to use the 
in-kernel ring buffer functionality.

Finally, while checking this out, I looked at a bunch of non virtualization device 
drivers currently in the kernel. And all the ones I looked at have 
implemented their own ring buffer. Is there a reason why this might be the case?
 
As usual, any help is appreciated.

Thanks,

Hank Janssen.

^ permalink raw reply

* VTDC2010 Deadline Extended to March 11
From: Ming Zhao @ 2010-03-03 15:56 UTC (permalink / raw)



[-- Attachment #1.1: Type: text/plain, Size: 5373 bytes --]

(our apologies if you receive this announcement multiple times)

Dead-line extension (March 11th) !

                   Call for Papers
                   ---------------

Workshop on Virtualization Technologies in Distributed Computing (VTDC 2010)

in conjunction with the 19-th International Symposium on High 
Performance Distributed Computing (HPDC-19)

Chicago, Illinois, USA, June 22, 2010
http://www.grid-appliance.org/wiki/index.php/VTDC10 
<http://www.grid-appliance.org/wiki/index.php/VTDC10>


WORKSHOP SCOPE

Virtualization has proven to be a powerful enabler in the field of 
distributed computing and has led to the emergence of the cloud 
computing paradigm and the provisioning of Infrastructure-as-a-Service 
(IaaS). This new paradigm raises challenges ranging from performance 
evaluation of IaaS platforms, through new methods of resource management 
including providing Service Level Agreements (SLAs) and energy- and 
cost-efficient schedules, to the emergence of supporting technologies 
such as virtual appliance management.

For the last three years, the VTDC workshop has served as a forum for 
the exchange of ideas and experiences studying the challenges and 
opportunities created by IaaS/cloud computing and virtualization 
technologies. VTDC brings together researchers in academia and industry 
who are involved in research and development on resource virtualization 
technologies and on techniques applied to the management of virtualized 
environments in distributed systems.

Topics of interest include but are not limited to:

VTDC 2010 topics of interest include, but are not limited to:

  * Infrastructure as a service (IaaS)
  * Virtualization in data centers
  * Virtualization for resource management and QoS assurance
  * Security aspects of using virtualization in a distributed environment
  * Virtual networks
  * Virtual data, storage as a service
  * Fault tolerance in virtualized environments
  * Virtualization in P2P systems
  * Virtualization-based adaptive/autonomic systems
  * The creation and management of environments/appliances
  * Virtualization technologies
  * Performance modeling (applications and systems)
  * Virtualization techniques for energy/thermal management
  * Case studies of applications on IaaS platforms
  * Deployment studies of virtualization technologies
  * Tools relevant to virtualization


SUBMISSION GUIDELINES

Submitted papers should be limited to 8 pages (including tables, images, 
and references) and should be formatted according to the ACM SIGS Style. 
Please use the official HPDC conference submission site to submit your 
paper; only pdf format is accepted. All papers will receive at least 
three reviews.
Submission implies the willingness of at least one of the authors to 
register
or the workshop and present the paper. The authors of the best paper in 
the workshop will receive a best-paper award.


PROCEEDINGS

The proceedings of the workshop will be published by the ACM.


IMPORTANT DATES

Submission deadline: March 11, 2010 (11:59 PM EST)
Author notification: March 26, 2010
Final papers due:    April 14, 2010
Workshop:           June 22, 2010


SUBMISSION SITE

Official HPDC conference submission site,
https://ssl.linklings.net/conferences/hpdc/ 
<https://ssl.linklings.net/conferences/hpdc/>


WORKSHOP WEBSITE

http://www.grid-appliance.org/wiki/index.php/VTDC10 
<http://www.grid-appliance.org/wiki/index.php/VTDC10>


WORKSHOP CHAIRS

General Chair: Renato Figueiredo, University of Florida

Program Chair: Frederic Desprez, INRIA

Steering Committee: Jose A. B. Fortes, University of Florida, Kate 
Keahey, University of Chicago, Argonne National Laboratory


PROGRAM COMMITTEE

-  James Broberg, The University of Melbourne, Australia
-  Franck Cappello, INRIA and University of Illinois at Urbana 
Champaign, USA
-  Dilma M Da silva, IBM Research, USA
-  Peter Dinda, Northwestern University, USA
-  Ian Foster, Argonne National Laboratory & The University of Chicago, USA
-  Sebastien Goasguen, Clemson University, USA
-  Kartik Gopalan, Computer Science, State University of New York at 
Binghamton, USA
-  Sverre Jarp, CERN, Switzerland
-  Thilo Kielmann, Vrije Universiteit, Amsterdam, Netherland
-  Jack Lange, Northwestern University, USA
-  Laurent Lefèvre, INRIA, University of Lyon, France
-  Ignacio Lorente, DSA-Research, Universidad Complutense de Madrid, Spain
-  Norbert Meyer, Poznan Supercomputing and Networking Center, Poland
-  Christine MORIN, INRIA Rennes - Bretagne Atlantique, France
-  D. K. Panda, The Ohio State University, USA
-  Matei Ripeanu, University of British Columbia, Canada
-  Paul Ruth, University of Mississippi, USA
-  Kyung D Ryu, IBM T.J. Watson Research Center, USA
-  Chris Samuel, The Victorian Partnership for Advanced Computing, Australia
-  Frank Siebenlist, Argonne National Laboratory, USA
-  Frederic Suter, CC IN2P3 / CNRS, France
-  Dongyan Xu, Purdue University, USA
-  Mike Wray, HP Labs, Bristol, UK
-  Mazin Yousif, IBM Corporation, USA
-  Ming Zhao, Florida International University, USA


CONTACT

For further information please contact
Frederic.Desprez@inria.fr <mailto:Frederic.Desprez@inria.fr> or 
renato@acis.ufl.edu <mailto:renato@acis.ufl.edu>

[-- Attachment #1.2: Type: text/html, Size: 6363 bytes --]

[-- Attachment #2: Type: text/plain, Size: 184 bytes --]

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

^ permalink raw reply

* Re: [RFC][ PATCH 0/3] vhost-net: Add mergeable RX buffer support to vhost-net
From: Michael S. Tsirkin @ 2010-03-03  9:28 UTC (permalink / raw)
  To: David Stevens; +Cc: kvm, netdev, rusty, virtualization
In-Reply-To: <OFF77F6422.A58B61AC-ON882576DB.002F6BA9-882576DB.0030ED4C@us.ibm.com>

On Wed, Mar 03, 2010 at 12:54:25AM -0800, David Stevens wrote:
> "Michael S. Tsirkin" <mst@redhat.com> wrote on 03/02/2010 11:54:32 PM:
> 
> > On Tue, Mar 02, 2010 at 04:20:03PM -0800, David Stevens wrote:
> > > These patches add support for mergeable receive buffers to
> > > vhost-net, allowing it to use multiple virtio buffer heads for a 
> single
> > > receive packet.
> > >                                         +-DLS
> > > 
> > > 
> > > Signed-off-by: David L Stevens <dlstevens@us.ibm.com>
> > 
> > Do you have performance numbers (both with and without mergeable buffers
> > in guest)?
> 
> Michael,
>         Nothing formal. I did some TCP single-stream throughput tests
> and was seeing 20-25% improvement on a laptop (ie, low-end hardware).
> That actually surprised me; I'd think it'd be about the same, except
> maybe in a test that has mixed packet sizes. Comparisons with the
> net-next kernel these patches are for showed only ~10% improvement.
>         But I also see a lot of variability both among different
> configurations and with the same configuration on different runs.
> So, I don't feel like those numbers are very solid, and I haven't
> yet done any tests on bigger hardware.

Interesting. Since the feature in question is billed first of all a
performance optimization, I think we might need some performance numbers
as a motivation.

Since the patches affect code paths when mergeable RX buffers are
disabled as well, I guess the most important point would be to verify
whether there's increase in latency and/or CPU utilization, or bandwidth
cost when the feature bit is *disabled*.

> 2 notes: I have a modified version of qemu to get the VHOST_FEATURES
> flags, including the mergeable RX bufs flag, passed to the guest; I'll
> be working with your current qemu git trees next, if any changes are
> needed to support it there.

This feature also seems to conflict with zero-copy rx patches from Xin
Xiaohui (subject: Provide a zero-copy method on KVM virtio-net) these
are not in a mergeable shape yet, so this is not a blocker, but I wonder
what your thoughts on the subject are: how will we do feature
negotiation if some backends don't support some features?

>         Second, I've found a missing initialization in the patches I
> sent on the list, so I'll send an updated patch 2 with the fix,

If you do, any chance you could use git send-email for this?

> and qemu patches when they are ready (plus any code-review comments
> incorporated).
> 

Pls take a look here as well
http://www.openfabrics.org/~mst/boring.txt


^ permalink raw reply

* Re: [RFC][ PATCH 0/3] vhost-net: Add mergeable RX buffer support to vhost-net
From: David Stevens @ 2010-03-03  8:54 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: kvm, netdev, rusty, virtualization
In-Reply-To: <20100303075432.GA14034@redhat.com>

"Michael S. Tsirkin" <mst@redhat.com> wrote on 03/02/2010 11:54:32 PM:

> On Tue, Mar 02, 2010 at 04:20:03PM -0800, David Stevens wrote:
> > These patches add support for mergeable receive buffers to
> > vhost-net, allowing it to use multiple virtio buffer heads for a 
single
> > receive packet.
> >                                         +-DLS
> > 
> > 
> > Signed-off-by: David L Stevens <dlstevens@us.ibm.com>
> 
> Do you have performance numbers (both with and without mergeable buffers
> in guest)?

Michael,
        Nothing formal. I did some TCP single-stream throughput tests
and was seeing 20-25% improvement on a laptop (ie, low-end hardware).
That actually surprised me; I'd think it'd be about the same, except
maybe in a test that has mixed packet sizes. Comparisons with the
net-next kernel these patches are for showed only ~10% improvement.
        But I also see a lot of variability both among different
configurations and with the same configuration on different runs.
So, I don't feel like those numbers are very solid, and I haven't
yet done any tests on bigger hardware.

2 notes: I have a modified version of qemu to get the VHOST_FEATURES
flags, including the mergeable RX bufs flag, passed to the guest; I'll
be working with your current qemu git trees next, if any changes are
needed to support it there.
        Second, I've found a missing initialization in the patches I
sent on the list, so I'll send an updated patch 2 with the fix, and
qemu patches when they are ready (plus any code-review comments
incorporated).

                                                                +-DLS


^ permalink raw reply

* Re: [RFC][ PATCH 0/3] vhost-net: Add mergeable RX buffer support to vhost-net
From: Michael S. Tsirkin @ 2010-03-03  7:54 UTC (permalink / raw)
  To: David Stevens; +Cc: rusty, netdev, kvm, virtualization
In-Reply-To: <OF8B8E9FD7.1F227ED3-ON882576DA.008312B5-882576DB.0001D5AB@us.ibm.com>

On Tue, Mar 02, 2010 at 04:20:03PM -0800, David Stevens wrote:
> These patches add support for mergeable receive buffers to
> vhost-net, allowing it to use multiple virtio buffer heads for a single
> receive packet.
>                                         +-DLS
> 
> 
> Signed-off-by: David L Stevens <dlstevens@us.ibm.com>

Do you have performance numbers (both with and without mergeable buffers
in guest)?

-- 
MST

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox