* [PATCHv11] vhost: vhost TX zero-copy support
From: Michael S. Tsirkin @ 2011-07-18 13:48 UTC (permalink / raw)
To: Shirley Ma; +Cc: netdev, jj, linux-kernel, kvm, virtualization
>From: Shirley Ma <mashirle@us.ibm.com>
This adds experimental zero copy support in vhost-net,
disabled by default. To enable, set
experimental_zcopytx module option to 1.
This patch maintains the outstanding userspace buffers in the
sequence it is delivered to vhost. The outstanding userspace buffers
will be marked as done once the lower device buffers DMA has finished.
This is monitored through last reference of kfree_skb callback. Two
buffer indices are used for this purpose.
The vhost-net device passes the userspace buffers info to lower device
skb through message control. DMA done status check and guest
notification are handled by handle_tx: in the worst case is all buffers
in the vq are in pending/done status, so we need to notify guest to
release DMA done buffers first before we get any new buffers from the
vq.
One known problem is that if the guest stops submitting
buffers, buffers might never get used until some
further action, e.g. device reset. This does not
seem to affect linux guests.
Signed-off-by: Shirley <xma@us.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
I run some light tests and this seems to work fine for me. Given that
the new functionality is disabled by default, it seems a pretty safe
patch to merge for 3.1.
Changes from v10:
don't leak ubuf_info
don't allocate ubuf_info for non zero copy vqs
Changes from v9:
coding style prettification suggested by Jesper Juhl
drivers/vhost/net.c | 77 +++++++++++++++++++++++++++++-
drivers/vhost/vhost.c | 128 +++++++++++++++++++++++++++++++++++++++++++------
drivers/vhost/vhost.h | 31 ++++++++++++
3 files changed, 220 insertions(+), 16 deletions(-)
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index e224a92..f0fd52c 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -12,6 +12,7 @@
#include <linux/virtio_net.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
#include <linux/rcupdate.h>
@@ -28,10 +29,18 @@
#include "vhost.h"
+static int experimental_zcopytx;
+module_param(experimental_zcopytx, int, 0444);
+MODULE_PARM_DESC(experimental_zcopytx, "Enable Experimental Zero Copy TX");
+
/* Max number of bytes transferred before requeueing the job.
* Using this limit prevents one virtqueue from starving others. */
#define VHOST_NET_WEIGHT 0x80000
+/* MAX number of TX used buffers for outstanding zerocopy */
+#define VHOST_MAX_PEND 128
+#define VHOST_GOODCOPY_LEN 256
+
enum {
VHOST_NET_VQ_RX = 0,
VHOST_NET_VQ_TX = 1,
@@ -54,6 +63,12 @@ struct vhost_net {
enum vhost_net_poll_state tx_poll_state;
};
+static bool vhost_sock_zcopy(struct socket *sock)
+{
+ return unlikely(experimental_zcopytx) &&
+ sock_flag(sock->sk, SOCK_ZEROCOPY);
+}
+
/* 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)
@@ -129,6 +144,8 @@ static void handle_tx(struct vhost_net *net)
int err, wmem;
size_t hdr_size;
struct socket *sock;
+ struct vhost_ubuf_ref *uninitialized_var(ubufs);
+ bool zcopy;
/* TODO: check that we are running from vhost_worker? */
sock = rcu_dereference_check(vq->private_data, 1);
@@ -149,8 +166,13 @@ static void handle_tx(struct vhost_net *net)
if (wmem < sock->sk->sk_sndbuf / 2)
tx_poll_stop(net);
hdr_size = vq->vhost_hlen;
+ zcopy = vhost_sock_zcopy(sock);
for (;;) {
+ /* Release DMAs done buffers first */
+ if (zcopy)
+ vhost_zerocopy_signal_used(vq);
+
head = vhost_get_vq_desc(&net->dev, vq, vq->iov,
ARRAY_SIZE(vq->iov),
&out, &in,
@@ -166,6 +188,13 @@ static void handle_tx(struct vhost_net *net)
set_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
break;
}
+ /* If more outstanding DMAs, queue the work */
+ if (unlikely(vq->upend_idx - vq->done_idx >
+ VHOST_MAX_PEND)) {
+ tx_poll_start(net, sock);
+ set_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
+ break;
+ }
if (unlikely(vhost_enable_notify(&net->dev, vq))) {
vhost_disable_notify(&net->dev, vq);
continue;
@@ -188,9 +217,39 @@ static void handle_tx(struct vhost_net *net)
iov_length(vq->hdr, s), hdr_size);
break;
}
+ /* use msg_control to pass vhost zerocopy ubuf info to skb */
+ if (zcopy) {
+ vq->heads[vq->upend_idx].id = head;
+ if (len < VHOST_GOODCOPY_LEN) {
+ /* copy don't need to wait for DMA done */
+ vq->heads[vq->upend_idx].len =
+ VHOST_DMA_DONE_LEN;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ ubufs = NULL;
+ } else {
+ struct ubuf_info *ubuf = &vq->ubuf_info[head];
+
+ vq->heads[vq->upend_idx].len = len;
+ ubuf->callback = vhost_zerocopy_callback;
+ ubuf->arg = vq->ubufs;
+ ubuf->desc = vq->upend_idx;
+ msg.msg_control = ubuf;
+ msg.msg_controllen = sizeof(ubuf);
+ ubufs = vq->ubufs;
+ kref_get(&ubufs->kref);
+ }
+ vq->upend_idx = (vq->upend_idx + 1) % UIO_MAXIOV;
+ }
/* TODO: Check specific error and bomb out unless ENOBUFS? */
err = sock->ops->sendmsg(NULL, sock, &msg, len);
if (unlikely(err < 0)) {
+ if (zcopy) {
+ if (ubufs)
+ vhost_ubuf_put(ubufs);
+ vq->upend_idx = ((unsigned)vq->upend_idx - 1) %
+ UIO_MAXIOV;
+ }
vhost_discard_vq_desc(vq, 1);
tx_poll_start(net, sock);
break;
@@ -198,7 +257,8 @@ static void handle_tx(struct vhost_net *net)
if (err != len)
pr_debug("Truncated TX packet: "
" len %d != %zd\n", err, len);
- vhost_add_used_and_signal(&net->dev, vq, head, 0);
+ if (!zcopy)
+ vhost_add_used_and_signal(&net->dev, vq, head, 0);
total_len += len;
if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
vhost_poll_queue(&vq->poll);
@@ -603,6 +663,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
{
struct socket *sock, *oldsock;
struct vhost_virtqueue *vq;
+ struct vhost_ubuf_ref *ubufs, *oldubufs = NULL;
int r;
mutex_lock(&n->dev.mutex);
@@ -632,6 +693,13 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
oldsock = rcu_dereference_protected(vq->private_data,
lockdep_is_held(&vq->mutex));
if (sock != oldsock) {
+ ubufs = vhost_ubuf_alloc(vq, sock && vhost_sock_zcopy(sock));
+ if (IS_ERR(ubufs)) {
+ r = PTR_ERR(ubufs);
+ goto err_ubufs;
+ }
+ oldubufs = vq->ubufs;
+ vq->ubufs = ubufs;
vhost_net_disable_vq(n, vq);
rcu_assign_pointer(vq->private_data, sock);
vhost_net_enable_vq(n, vq);
@@ -639,6 +707,9 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
mutex_unlock(&vq->mutex);
+ if (oldubufs)
+ vhost_ubuf_put_and_wait(oldubufs);
+
if (oldsock) {
vhost_net_flush_vq(n, index);
fput(oldsock->file);
@@ -647,6 +718,8 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
mutex_unlock(&n->dev.mutex);
return 0;
+err_ubufs:
+ fput(sock->file);
err_vq:
mutex_unlock(&vq->mutex);
err:
@@ -776,6 +849,8 @@ static struct miscdevice vhost_net_misc = {
static int vhost_net_init(void)
{
+ if (experimental_zcopytx)
+ vhost_enable_zcopy(VHOST_NET_VQ_TX);
return misc_register(&vhost_net_misc);
}
module_init(vhost_net_init);
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index ea966b3..5ef2f62 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -37,6 +37,8 @@ enum {
VHOST_MEMORY_F_LOG = 0x1,
};
+static unsigned vhost_zcopy_mask __read_mostly;
+
#define vhost_used_event(vq) ((u16 __user *)&vq->avail->ring[vq->num])
#define vhost_avail_event(vq) ((u16 __user *)&vq->used->ring[vq->num])
@@ -179,6 +181,9 @@ static void vhost_vq_reset(struct vhost_dev *dev,
vq->call_ctx = NULL;
vq->call = NULL;
vq->log_ctx = NULL;
+ vq->upend_idx = 0;
+ vq->done_idx = 0;
+ vq->ubufs = NULL;
}
static int vhost_worker(void *data)
@@ -225,10 +230,28 @@ static int vhost_worker(void *data)
return 0;
}
+static void vhost_vq_free_iovecs(struct vhost_virtqueue *vq)
+{
+ kfree(vq->indirect);
+ vq->indirect = NULL;
+ kfree(vq->log);
+ vq->log = NULL;
+ kfree(vq->heads);
+ vq->heads = NULL;
+ kfree(vq->ubuf_info);
+ vq->ubuf_info = NULL;
+}
+
+void vhost_enable_zcopy(int vq)
+{
+ vhost_zcopy_mask |= 0x1 << vq;
+}
+
/* Helper to allocate iovec buffers for all vqs. */
static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
{
int i;
+ bool zcopy;
for (i = 0; i < dev->nvqs; ++i) {
dev->vqs[i].indirect = kmalloc(sizeof *dev->vqs[i].indirect *
@@ -237,19 +260,21 @@ static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
GFP_KERNEL);
dev->vqs[i].heads = kmalloc(sizeof *dev->vqs[i].heads *
UIO_MAXIOV, GFP_KERNEL);
-
+ zcopy = vhost_zcopy_mask & (0x1 << i);
+ if (zcopy)
+ dev->vqs[i].ubuf_info =
+ kmalloc(sizeof *dev->vqs[i].ubuf_info *
+ UIO_MAXIOV, GFP_KERNEL);
if (!dev->vqs[i].indirect || !dev->vqs[i].log ||
- !dev->vqs[i].heads)
+ !dev->vqs[i].heads ||
+ (zcopy && !dev->vqs[i].ubuf_info))
goto err_nomem;
}
return 0;
err_nomem:
- for (; i >= 0; --i) {
- kfree(dev->vqs[i].indirect);
- kfree(dev->vqs[i].log);
- kfree(dev->vqs[i].heads);
- }
+ for (; i >= 0; --i)
+ vhost_vq_free_iovecs(&dev->vqs[i]);
return -ENOMEM;
}
@@ -257,14 +282,8 @@ static void vhost_dev_free_iovecs(struct vhost_dev *dev)
{
int i;
- for (i = 0; i < dev->nvqs; ++i) {
- kfree(dev->vqs[i].indirect);
- dev->vqs[i].indirect = NULL;
- kfree(dev->vqs[i].log);
- dev->vqs[i].log = NULL;
- kfree(dev->vqs[i].heads);
- dev->vqs[i].heads = NULL;
- }
+ for (i = 0; i < dev->nvqs; ++i)
+ vhost_vq_free_iovecs(&dev->vqs[i]);
}
long vhost_dev_init(struct vhost_dev *dev,
@@ -287,6 +306,7 @@ long vhost_dev_init(struct vhost_dev *dev,
dev->vqs[i].log = NULL;
dev->vqs[i].indirect = NULL;
dev->vqs[i].heads = NULL;
+ dev->vqs[i].ubuf_info = NULL;
dev->vqs[i].dev = dev;
mutex_init(&dev->vqs[i].mutex);
vhost_vq_reset(dev, dev->vqs + i);
@@ -390,6 +410,30 @@ long vhost_dev_reset_owner(struct vhost_dev *dev)
return 0;
}
+/* In case of DMA done not in order in lower device driver for some reason.
+ * upend_idx is used to track end of used idx, done_idx is used to track head
+ * of used idx. Once lower device DMA done contiguously, we will signal KVM
+ * guest used idx.
+ */
+int vhost_zerocopy_signal_used(struct vhost_virtqueue *vq)
+{
+ int i;
+ int j = 0;
+
+ for (i = vq->done_idx; i != vq->upend_idx; i = (i + 1) % UIO_MAXIOV) {
+ if ((vq->heads[i].len == VHOST_DMA_DONE_LEN)) {
+ vq->heads[i].len = VHOST_DMA_CLEAR_LEN;
+ vhost_add_used_and_signal(vq->dev, vq,
+ vq->heads[i].id, 0);
+ ++j;
+ } else
+ break;
+ }
+ if (j)
+ vq->done_idx = i;
+ return j;
+}
+
/* Caller should have device mutex */
void vhost_dev_cleanup(struct vhost_dev *dev)
{
@@ -400,6 +444,13 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
vhost_poll_stop(&dev->vqs[i].poll);
vhost_poll_flush(&dev->vqs[i].poll);
}
+ /* Wait for all lower device DMAs done. */
+ if (dev->vqs[i].ubufs)
+ vhost_ubuf_put_and_wait(dev->vqs[i].ubufs);
+
+ /* Signal guest as appropriate. */
+ vhost_zerocopy_signal_used(&dev->vqs[i]);
+
if (dev->vqs[i].error_ctx)
eventfd_ctx_put(dev->vqs[i].error_ctx);
if (dev->vqs[i].error)
@@ -1486,3 +1537,50 @@ void vhost_disable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
&vq->used->flags, r);
}
}
+
+static void vhost_zerocopy_done_signal(struct kref *kref)
+{
+ struct vhost_ubuf_ref *ubufs = container_of(kref, struct vhost_ubuf_ref,
+ kref);
+ wake_up(&ubufs->wait);
+}
+
+struct vhost_ubuf_ref *vhost_ubuf_alloc(struct vhost_virtqueue *vq,
+ bool zcopy)
+{
+ struct vhost_ubuf_ref *ubufs;
+ /* No zero copy backend? Nothing to count. */
+ if (!zcopy)
+ return NULL;
+ ubufs = kmalloc(sizeof *ubufs, GFP_KERNEL);
+ if (!ubufs)
+ return ERR_PTR(-ENOMEM);
+ kref_init(&ubufs->kref);
+ kref_get(&ubufs->kref);
+ init_waitqueue_head(&ubufs->wait);
+ ubufs->vq = vq;
+ return ubufs;
+}
+
+void vhost_ubuf_put(struct vhost_ubuf_ref *ubufs)
+{
+ kref_put(&ubufs->kref, vhost_zerocopy_done_signal);
+}
+
+void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *ubufs)
+{
+ kref_put(&ubufs->kref, vhost_zerocopy_done_signal);
+ wait_event(ubufs->wait, !atomic_read(&ubufs->kref.refcount));
+ kfree(ubufs);
+}
+
+void vhost_zerocopy_callback(void *arg)
+{
+ struct ubuf_info *ubuf = arg;
+ struct vhost_ubuf_ref *ubufs = ubuf->arg;
+ struct vhost_virtqueue *vq = ubufs->vq;
+
+ /* set len = 1 to mark this desc buffers done DMA */
+ vq->heads[ubuf->desc].len = VHOST_DMA_DONE_LEN;
+ kref_put(&ubufs->kref, vhost_zerocopy_done_signal);
+}
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index 8e03379..1544b78 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -13,6 +13,11 @@
#include <linux/virtio_ring.h>
#include <asm/atomic.h>
+/* This is for zerocopy, used buffer len is set to 1 when lower device DMA
+ * done */
+#define VHOST_DMA_DONE_LEN 1
+#define VHOST_DMA_CLEAR_LEN 0
+
struct vhost_device;
struct vhost_work;
@@ -50,6 +55,18 @@ struct vhost_log {
u64 len;
};
+struct vhost_virtqueue;
+
+struct vhost_ubuf_ref {
+ struct kref kref;
+ wait_queue_head_t wait;
+ struct vhost_virtqueue *vq;
+};
+
+struct vhost_ubuf_ref *vhost_ubuf_alloc(struct vhost_virtqueue *, bool zcopy);
+void vhost_ubuf_put(struct vhost_ubuf_ref *);
+void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *);
+
/* The virtqueue structure describes a queue attached to a device. */
struct vhost_virtqueue {
struct vhost_dev *dev;
@@ -114,6 +131,16 @@ struct vhost_virtqueue {
/* Log write descriptors */
void __user *log_base;
struct vhost_log *log;
+ /* vhost zerocopy support fields below: */
+ /* last used idx for outstanding DMA zerocopy buffers */
+ int upend_idx;
+ /* first used idx for DMA done zerocopy buffers */
+ int done_idx;
+ /* an array of userspace buffers info */
+ struct ubuf_info *ubuf_info;
+ /* Reference counting for outstanding ubufs.
+ * Protected by vq mutex. Writers must also take device mutex. */
+ struct vhost_ubuf_ref *ubufs;
};
struct vhost_dev {
@@ -160,6 +187,8 @@ bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *);
int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
unsigned int log_num, u64 len);
+void vhost_zerocopy_callback(void *arg);
+int vhost_zerocopy_signal_used(struct vhost_virtqueue *vq);
#define vq_err(vq, fmt, ...) do { \
pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \
@@ -186,4 +215,6 @@ static inline int vhost_has_feature(struct vhost_dev *dev, int bit)
return acked_features & (1 << bit);
}
+void vhost_enable_zcopy(int vq);
+
#endif
--
1.7.5.53.gc233e
^ permalink raw reply related
* RE: [PATCH 1/1] Staging: hv: Integrate the time source driver with Hyper-V detection code
From: KY Srinivasan @ 2011-07-18 14:53 UTC (permalink / raw)
To: KY Srinivasan, gregkh@suse.de, linux-kernel@vger.kernel.org,
"devel@linuxdriverproject.org" <devel>
Cc: Haiyang Zhang
In-Reply-To: <1310778074-31664-1-git-send-email-kys@microsoft.com>
> -----Original Message-----
> From: K. Y. Srinivasan [mailto:kys@microsoft.com]
> Sent: Friday, July 15, 2011 9:01 PM
> To: gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org; tglx@linutronix.de
> Cc: KY Srinivasan; Haiyang Zhang
> Subject: [PATCH 1/1] Staging: hv: Integrate the time source driver with Hyper-V
> detection code
>
> The Hyper-V timesource driver is best integrated with Hyper-V detection code
> since: (a) Linux guests running on Hyper-V need this timesource and (b)
> by integrating with Hyper-V detection, we could significantly minimize the
> code in the timesource driver.
Thomas,
A number of weeks ago you had reviewed the time Hyper-V time source driver code
and recommended that I merge it with Hyper-V detection code. That is exactly what I
have done here. Is this what you had in mind; your feedback would be greatly appreciated.
I had sent this patch a couple of weeks ago and got no response. As an X86 maintainer,
would you be willing to take this patch.
Regards,
K. Y
>
> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
> Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
> ---
> arch/x86/kernel/cpu/mshyperv.c | 24 ++++++++
> drivers/staging/hv/Makefile | 2 +-
> drivers/staging/hv/hv_timesource.c | 102 ------------------------------------
> 3 files changed, 25 insertions(+), 103 deletions(-)
> delete mode 100644 drivers/staging/hv/hv_timesource.c
>
> diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
> index d944bf6..c97f88d 100644
> --- a/arch/x86/kernel/cpu/mshyperv.c
> +++ b/arch/x86/kernel/cpu/mshyperv.c
> @@ -11,6 +11,8 @@
> */
>
> #include <linux/types.h>
> +#include <linux/time.h>
> +#include <linux/clocksource.h>
> #include <linux/module.h>
> #include <asm/processor.h>
> #include <asm/hypervisor.h>
> @@ -36,6 +38,25 @@ static bool __init ms_hyperv_platform(void)
> !memcmp("Microsoft Hv", hyp_signature, 12);
> }
>
> +static cycle_t read_hv_clock(struct clocksource *arg)
> +{
> + cycle_t current_tick;
> + /*
> + * Read the partition counter to get the current tick count. This count
> + * is set to 0 when the partition is created and is incremented in
> + * 100 nanosecond units.
> + */
> + rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
> + return current_tick;
> +}
> +
> +static struct clocksource hyperv_cs = {
> + .name = "hyperv_clocksource",
> + .rating = 400, /* use this when running on Hyperv*/
> + .read = read_hv_clock,
> + .mask = CLOCKSOURCE_MASK(64),
> +};
> +
> static void __init ms_hyperv_init_platform(void)
> {
> /*
> @@ -46,6 +67,9 @@ static void __init ms_hyperv_init_platform(void)
>
> printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n",
> ms_hyperv.features, ms_hyperv.hints);
> +
> +
> + clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100);
> }
>
> const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
> diff --git a/drivers/staging/hv/Makefile b/drivers/staging/hv/Makefile
> index bd176b1..3e0d7e6 100644
> --- a/drivers/staging/hv/Makefile
> +++ b/drivers/staging/hv/Makefile
> @@ -1,4 +1,4 @@
> -obj-$(CONFIG_HYPERV) += hv_vmbus.o hv_timesource.o
> +obj-$(CONFIG_HYPERV) += hv_vmbus.o
> obj-$(CONFIG_HYPERV_STORAGE) += hv_storvsc.o
> obj-$(CONFIG_HYPERV_NET) += hv_netvsc.o
> obj-$(CONFIG_HYPERV_UTILS) += hv_utils.o
> diff --git a/drivers/staging/hv/hv_timesource.c
> b/drivers/staging/hv/hv_timesource.c
> deleted file mode 100644
> index 0efb049..0000000
> --- a/drivers/staging/hv/hv_timesource.c
> +++ /dev/null
> @@ -1,102 +0,0 @@
> -/*
> - * A clocksource for Linux running on HyperV.
> - *
> - *
> - * Copyright (C) 2010, Novell, Inc.
> - * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License version 2 as
> - * published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> - * NON INFRINGEMENT. See the GNU General Public License for more
> - * details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
> - *
> - */
> -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> -
> -#include <linux/version.h>
> -#include <linux/clocksource.h>
> -#include <linux/init.h>
> -#include <linux/module.h>
> -#include <linux/pci.h>
> -#include <linux/dmi.h>
> -#include <asm/hyperv.h>
> -#include <asm/mshyperv.h>
> -#include <asm/hypervisor.h>
> -
> -#define HV_CLOCK_SHIFT 22
> -
> -static cycle_t read_hv_clock(struct clocksource *arg)
> -{
> - cycle_t current_tick;
> - /*
> - * Read the partition counter to get the current tick count. This count
> - * is set to 0 when the partition is created and is incremented in
> - * 100 nanosecond units.
> - */
> - rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
> - return current_tick;
> -}
> -
> -static struct clocksource hyperv_cs = {
> - .name = "hyperv_clocksource",
> - .rating = 400, /* use this when running on Hyperv*/
> - .read = read_hv_clock,
> - .mask = CLOCKSOURCE_MASK(64),
> - /*
> - * The time ref counter in HyperV is in 100ns units.
> - * The definition of mult is:
> - * mult/2^shift = ns/cyc = 100
> - * mult = (100 << shift)
> - */
> - .mult = (100 << HV_CLOCK_SHIFT),
> - .shift = HV_CLOCK_SHIFT,
> -};
> -
> -static const struct dmi_system_id __initconst
> -hv_timesource_dmi_table[] __maybe_unused = {
> - {
> - .ident = "Hyper-V",
> - .matches = {
> - DMI_MATCH(DMI_SYS_VENDOR, "Microsoft
> Corporation"),
> - DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
> - DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
> - },
> - },
> - { },
> -};
> -MODULE_DEVICE_TABLE(dmi, hv_timesource_dmi_table);
> -
> -static const struct pci_device_id __initconst
> -hv_timesource_pci_table[] __maybe_unused = {
> - { PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */
> - { 0 }
> -};
> -MODULE_DEVICE_TABLE(pci, hv_timesource_pci_table);
> -
> -
> -static int __init init_hv_clocksource(void)
> -{
> - if ((x86_hyper != &x86_hyper_ms_hyperv) ||
> - !(ms_hyperv.features &
> HV_X64_MSR_TIME_REF_COUNT_AVAILABLE))
> - return -ENODEV;
> -
> - if (!dmi_check_system(hv_timesource_dmi_table))
> - return -ENODEV;
> -
> - pr_info("Registering HyperV clock source\n");
> - return clocksource_register(&hyperv_cs);
> -}
> -
> -module_init(init_hv_clocksource);
> -MODULE_DESCRIPTION("HyperV based clocksource");
> -MODULE_AUTHOR("K. Y. Srinivasan <ksrinivasan@novell.com>");
> -MODULE_LICENSE("GPL");
> --
> 1.7.4.1
>
^ permalink raw reply
* Re: [PATCHv11] vhost: vhost TX zero-copy support
From: David Miller @ 2011-07-18 17:43 UTC (permalink / raw)
To: mst; +Cc: kvm, netdev, mashirle, linux-kernel, virtualization, jj
In-Reply-To: <20110718134846.GA7107@redhat.com>
From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Mon, 18 Jul 2011 16:48:46 +0300
>>From: Shirley Ma <mashirle@us.ibm.com>
>
> This adds experimental zero copy support in vhost-net,
> disabled by default. To enable, set
> experimental_zcopytx module option to 1.
>
> This patch maintains the outstanding userspace buffers in the
> sequence it is delivered to vhost. The outstanding userspace buffers
> will be marked as done once the lower device buffers DMA has finished.
> This is monitored through last reference of kfree_skb callback. Two
> buffer indices are used for this purpose.
>
> The vhost-net device passes the userspace buffers info to lower device
> skb through message control. DMA done status check and guest
> notification are handled by handle_tx: in the worst case is all buffers
> in the vq are in pending/done status, so we need to notify guest to
> release DMA done buffers first before we get any new buffers from the
> vq.
>
> One known problem is that if the guest stops submitting
> buffers, buffers might never get used until some
> further action, e.g. device reset. This does not
> seem to affect linux guests.
>
> Signed-off-by: Shirley <xma@us.ibm.com>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Applied, thanks!
^ permalink raw reply
* [PATCH RFC] vhost: fix zcopy reference counting
From: Michael S. Tsirkin @ 2011-07-19 10:33 UTC (permalink / raw)
To: mashirle; +Cc: netdev, linux-kernel, kvm, virtualization
Fix get/put refcount imbalance with zero copy,
which caused qemu to hang forever on guest driver unload.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
Dave, I've put this on my tree so no need for you to bother.
drivers/vhost/vhost.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 46822c0..c16d225 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1578,7 +1578,6 @@ struct vhost_ubuf_ref *vhost_ubuf_alloc(struct vhost_virtqueue *vq,
if (!ubufs)
return ERR_PTR(-ENOMEM);
kref_init(&ubufs->kref);
- kref_get(&ubufs->kref);
init_waitqueue_head(&ubufs->wait);
ubufs->vq = vq;
return ubufs;
--
1.7.5.53.gc233e
^ permalink raw reply related
* [PATCH RFC] vhost: optimize interrupt enable/disable
From: Michael S. Tsirkin @ 2011-07-19 15:04 UTC (permalink / raw)
To: Jason Wang; +Cc: netdev, linux-kernel, kvm, virtualization
As we now only update used ring after enabling
the backend, we can write flags with __put_user:
as that's done on data path, it matters.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
It seems an obvious optimization so I queued this up
already.
drivers/vhost/vhost.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index c16d225..c14c42b 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -998,7 +998,7 @@ int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
static int vhost_update_used_flags(struct vhost_virtqueue *vq)
{
void __user *used;
- if (put_user(vq->used_flags, &vq->used->flags) < 0)
+ if (__put_user(vq->used_flags, &vq->used->flags) < 0)
return -EFAULT;
if (unlikely(vq->log_used)) {
/* Make sure the flag is seen before log. */
@@ -1016,7 +1016,7 @@ static int vhost_update_used_flags(struct vhost_virtqueue *vq)
static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event)
{
- if (put_user(vq->avail_idx, vhost_avail_event(vq)))
+ if (__put_user(vq->avail_idx, vhost_avail_event(vq)))
return -EFAULT;
if (unlikely(vq->log_used)) {
void __user *used;
--
1.7.5.53.gc233e
^ permalink raw reply related
* [PATCH 0/8] Staging: hv: Driver cleanup
From: K. Y. Srinivasan @ 2011-07-19 18:43 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization; +Cc: K. Y. Srinivasan
Further cleanup of the hv drivers:
1) Cleanup all remaining checkpatch warnings/errors.
2) Get rid of items from the TODO file that have been either
completed or cannot be done.
3) Update the TODO file to reflect the current status.
Regards,
K. Y
^ permalink raw reply
* [PATCH 1/8] Staging: hv: vmbus: Fix a checkpatch warning in ring_buffer.c
From: K. Y. Srinivasan @ 2011-07-19 18:44 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang
In-Reply-To: <1311101018-23370-1-git-send-email-kys@microsoft.com>
Fix a checkpatch warning in ring_buffer.c (line over 80 characters).
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/staging/hv/ring_buffer.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/staging/hv/ring_buffer.c b/drivers/staging/hv/ring_buffer.c
index 9212699..e41d206 100644
--- a/drivers/staging/hv/ring_buffer.c
+++ b/drivers/staging/hv/ring_buffer.c
@@ -34,7 +34,8 @@
/* Amount of space to write to */
-#define BYTES_AVAIL_TO_WRITE(r, w, z) ((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w))
+#define BYTES_AVAIL_TO_WRITE(r, w, z) \
+(((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w)))
/*
--
1.7.4.1
^ permalink raw reply related
* [PATCH 2/8] Staging: hv: vmbus: Fix checkpatch warnings in connection.c
From: K. Y. Srinivasan @ 2011-07-19 18:44 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization
Cc: K. Y. Srinivasan, Haiyang Zhang
In-Reply-To: <1311101065-23417-1-git-send-email-kys@microsoft.com>
Fix bunch of checkpatch warnings in connection.c
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/staging/hv/connection.c | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/staging/hv/connection.c b/drivers/staging/hv/connection.c
index 6aab802..66b7c4b 100644
--- a/drivers/staging/hv/connection.c
+++ b/drivers/staging/hv/connection.c
@@ -224,11 +224,11 @@ static void process_chn_event(u32 relid)
channel = relid2channel(relid);
spin_lock_irqsave(&channel->inbound_lock, flags);
- if (channel && (channel->onchannel_callback != NULL)) {
+ if (channel && (channel->onchannel_callback != NULL))
channel->onchannel_callback(channel->channel_callback_context);
- } else {
+ else
pr_err("channel not found for relid - %u\n", relid);
- }
+
spin_unlock_irqrestore(&channel->inbound_lock, flags);
}
@@ -250,16 +250,17 @@ void vmbus_on_event(unsigned long data)
if (!recv_int_page[dword])
continue;
for (bit = 0; bit < 32; bit++) {
- if (sync_test_and_clear_bit(bit, (unsigned long *)&recv_int_page[dword])) {
+ if (sync_test_and_clear_bit(bit,
+ (unsigned long *)&recv_int_page[dword])) {
relid = (dword << 5) + bit;
- if (relid == 0) {
+ if (relid == 0)
/*
* Special case - vmbus
* channel protocol msg
*/
continue;
- }
+
process_chn_event(relid);
}
}
--
1.7.4.1
^ permalink raw reply related
* [PATCH 3/8] Staging: hv: tools: Fix a checkpatch warning in hv_kvp_daemon.c
From: K. Y. Srinivasan @ 2011-07-19 18:44 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang
In-Reply-To: <1311101065-23417-1-git-send-email-kys@microsoft.com>
Fix a checkpatch warning in hv_kvp_daemon.c.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/staging/hv/tools/hv_kvp_daemon.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/staging/hv/tools/hv_kvp_daemon.c b/drivers/staging/hv/tools/hv_kvp_daemon.c
index 33f0f1c..c230bae 100644
--- a/drivers/staging/hv/tools/hv_kvp_daemon.c
+++ b/drivers/staging/hv/tools/hv_kvp_daemon.c
@@ -117,7 +117,7 @@ void kvp_get_os_info(void)
uname(&uts_buf);
os_build = uts_buf.release;
- processor_arch= uts_buf.machine;
+ processor_arch = uts_buf.machine;
file = fopen("/etc/SuSE-release", "r");
if (file != NULL)
--
1.7.4.1
^ permalink raw reply related
* [PATCH 4/8] Staging: hv: vmbus: Fix checkpatch warnings
From: K. Y. Srinivasan @ 2011-07-19 18:44 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization
Cc: K. Y. Srinivasan, Haiyang Zhang
In-Reply-To: <1311101065-23417-1-git-send-email-kys@microsoft.com>
Fix checkpatch warnings in hv.c
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/staging/hv/hv.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/hv/hv.c b/drivers/staging/hv/hv.c
index e733173..14e6315 100644
--- a/drivers/staging/hv/hv.c
+++ b/drivers/staging/hv/hv.c
@@ -111,7 +111,7 @@ static u64 do_hypercall(u64 control, void *input, void *output)
u64 hv_status = 0;
u64 input_address = (input) ? virt_to_phys(input) : 0;
u64 output_address = (output) ? virt_to_phys(output) : 0;
- volatile void *hypercall_page = hv_context.hypercall_page;
+ void *hypercall_page = hv_context.hypercall_page;
__asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8");
__asm__ __volatile__("call *%3" : "=a" (hv_status) :
@@ -132,7 +132,7 @@ static u64 do_hypercall(u64 control, void *input, void *output)
u64 output_address = (output) ? virt_to_phys(output) : 0;
u32 output_address_hi = output_address >> 32;
u32 output_address_lo = output_address & 0xFFFFFFFF;
- volatile void *hypercall_page = hv_context.hypercall_page;
+ void *hypercall_page = hv_context.hypercall_page;
__asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi),
"=a"(hv_status_lo) : "d" (control_hi),
--
1.7.4.1
^ permalink raw reply related
* [PATCH 5/8] Staging: hv: mousevsc: Fix checkpatch errors and warnings
From: K. Y. Srinivasan @ 2011-07-19 18:44 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization
Cc: K. Y. Srinivasan, Haiyang Zhang
In-Reply-To: <1311101065-23417-1-git-send-email-kys@microsoft.com>
Fix checkpatch errors and warnings.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/staging/hv/hv_mouse.c | 58 +++++++++++++++++++++-------------------
1 files changed, 30 insertions(+), 28 deletions(-)
diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c
index 28bd2c5..e95bd3a 100644
--- a/drivers/staging/hv/hv_mouse.c
+++ b/drivers/staging/hv/hv_mouse.c
@@ -53,7 +53,7 @@ struct hv_input_dev_info {
(SYNTHHID_INPUT_VERSION_MAJOR << 16))
-#pragma pack(push,1)
+#pragma pack(push, 1)
/*
* Message types in the synthetic input protocol
*/
@@ -119,8 +119,8 @@ struct synthhid_input_report {
#pragma pack(pop)
-#define INPUTVSC_SEND_RING_BUFFER_SIZE 10*PAGE_SIZE
-#define INPUTVSC_RECV_RING_BUFFER_SIZE 10*PAGE_SIZE
+#define INPUTVSC_SEND_RING_BUFFER_SIZE (10 * PAGE_SIZE)
+#define INPUTVSC_RECV_RING_BUFFER_SIZE (10 * PAGE_SIZE)
#define NBITS(x) (((x)/BITS_PER_LONG)+1)
@@ -177,7 +177,8 @@ struct mousevsc_dev {
static const char *driver_name = "mousevsc";
-static void deviceinfo_callback(struct hv_device *dev, struct hv_input_dev_info *info);
+static void deviceinfo_callback(struct hv_device *dev,
+ struct hv_input_dev_info *info);
static void inputreport_callback(struct hv_device *dev, void *packet, u32 len);
static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len);
@@ -336,7 +337,8 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
input_device->hid_desc = kzalloc(desc->bLength, GFP_KERNEL);
if (!input_device->hid_desc) {
- pr_err("unable to allocate hid descriptor - size %d", desc->bLength);
+ pr_err("unable to allocate hid descriptor - size %d",
+ desc->bLength);
goto cleanup;
}
@@ -502,22 +504,21 @@ static void mousevsc_on_channel_callback(void *context)
desc = (struct vmpacket_descriptor *)buffer;
switch (desc->type) {
- case VM_PKT_COMP:
- mousevsc_on_send_completion(
- device, desc);
- break;
-
- case VM_PKT_DATA_INBAND:
- mousevsc_on_receive(
- device, desc);
- break;
-
- default:
- pr_err("unhandled packet type %d, tid %llx len %d\n",
- desc->type,
- req_id,
- bytes_recvd);
- break;
+ case VM_PKT_COMP:
+ mousevsc_on_send_completion(
+ device, desc);
+ break;
+
+ case VM_PKT_DATA_INBAND:
+ mousevsc_on_receive(
+ device, desc);
+ break;
+
+ default:
+ pr_err("unhandled packet type %d, tid %llx len %d\n",
+ desc->type, req_id,
+ bytes_recvd);
+ break;
}
/* reset */
@@ -596,12 +597,12 @@ static int mousevsc_connect_to_vsp(struct hv_device *device)
pr_info("synthhid protocol request...");
ret = vmbus_sendpacket(device->channel, request,
- sizeof(struct pipe_prt_msg) -
- sizeof(unsigned char) +
- sizeof(struct synthhid_protocol_request),
- (unsigned long)request,
- VM_PKT_DATA_INBAND,
- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+ sizeof(struct pipe_prt_msg) -
+ sizeof(unsigned char) +
+ sizeof(struct synthhid_protocol_request),
+ (unsigned long)request,
+ VM_PKT_DATA_INBAND,
+ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
if (ret != 0) {
pr_err("unable to send synthhid protocol request.");
goto cleanup;
@@ -766,7 +767,8 @@ struct input_device_context {
};
-static void deviceinfo_callback(struct hv_device *dev, struct hv_input_dev_info *info)
+static void deviceinfo_callback(struct hv_device *dev,
+ struct hv_input_dev_info *info)
{
struct input_device_context *input_device_ctx =
dev_get_drvdata(&dev->device);
--
1.7.4.1
^ permalink raw reply related
* [PATCH 6/8] Staging: hv: Get rid of checkpatch cleanup item
From: K. Y. Srinivasan @ 2011-07-19 18:44 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization
Cc: K. Y. Srinivasan, Haiyang Zhang
In-Reply-To: <1311101065-23417-1-git-send-email-kys@microsoft.com>
All checkpatch warnings/errors have been addressed and fixed. Patches have been
been submitted to address the remaining issues.
Signed-off-by: K. Y. Srinivasan <kys@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 582fd4a..b6335ff 100644
--- a/drivers/staging/hv/TODO
+++ b/drivers/staging/hv/TODO
@@ -1,5 +1,4 @@
TODO:
- - fix remaining checkpatch warnings and errors
- audit the vmbus to verify it is working properly with the
driver model
- see if the vmbus can be merged with the other virtual busses
--
1.7.4.1
^ permalink raw reply related
* [PATCH 7/8] Staging: hv: Get rid of the vmbus merge item
From: K. Y. Srinivasan @ 2011-07-19 18:44 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang
In-Reply-To: <1311101065-23417-1-git-send-email-kys@microsoft.com>
The host/guest transport is very host centric. Given this, it is unlikely
that we will be able to merge vmbus with other host/guest buses in the kernel.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/staging/hv/TODO | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/hv/TODO b/drivers/staging/hv/TODO
index b6335ff..8b4c97a 100644
--- a/drivers/staging/hv/TODO
+++ b/drivers/staging/hv/TODO
@@ -1,8 +1,6 @@
TODO:
- audit the vmbus to verify it is working properly with the
driver model
- - see if the vmbus can be merged with the other virtual busses
- in the kernel
- audit the network driver
- checking for carrier inside open is wrong, network device API
confusion??
--
1.7.4.1
^ permalink raw reply related
* [PATCH 8/8] Staging: hv: Update the TODO file
From: K. Y. Srinivasan @ 2011-07-19 18:44 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization; +Cc: Haiyang Zhang
In-Reply-To: <1311101065-23417-1-git-send-email-kys@microsoft.com>
The TODO file has not been updated in a long time. Update this file
to reflect the current status.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/staging/hv/TODO | 21 ++++++++++++++++++++-
1 files changed, 20 insertions(+), 1 deletions(-)
diff --git a/drivers/staging/hv/TODO b/drivers/staging/hv/TODO
index 8b4c97a..23c74ed 100644
--- a/drivers/staging/hv/TODO
+++ b/drivers/staging/hv/TODO
@@ -1,11 +1,30 @@
TODO:
- audit the vmbus to verify it is working properly with the
driver model
+
+ STATUS (July 19, 2011):
+ All outstanding issues (known to us) with regards
+ to conforming to Linux Driver Model have been addressed.
+
- audit the network driver
- checking for carrier inside open is wrong, network device API
confusion??
+
+ STATUS (July 19, 2011):
+ The network driver has been reviewed by the community.
+ We have addressed the various issues that were raised in this
+ review.
+
- audit the block driver
- audit the scsi driver
+ STATUS (July 19, 2011):
+ One of the longstanding comment on this body of code
+ has been to merge the block and scsi driver. This has been done
+ and patches have been submitted. We have also addressed all the
+ review comments on this body of code.
+
+
Please send patches for this code to Greg Kroah-Hartman <gregkh@suse.de>,
-Hank Janssen <hjanssen@microsoft.com>, and Haiyang Zhang <haiyangz@microsoft.com>.
+Hank Janssen <hjanssen@microsoft.com>, and Haiyang Zhang <haiyangz@microsoft.com>,
+K. Y. Srinivasan <kys@microsoft.com>.
--
1.7.4.1
^ permalink raw reply related
* Re: [PATCH 5/8] Staging: hv: mousevsc: Fix checkpatch errors and warnings
From: Joe Perches @ 2011-07-19 19:28 UTC (permalink / raw)
To: K. Y. Srinivasan
Cc: gregkh, linux-kernel, devel, virtualization, Haiyang Zhang
In-Reply-To: <1311101065-23417-5-git-send-email-kys@microsoft.com>
On Tue, 2011-07-19 at 11:44 -0700, K. Y. Srinivasan wrote:
> Fix checkpatch errors and warnings.
[]
> diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c
[]
> @@ -53,7 +53,7 @@ struct hv_input_dev_info {
> -#pragma pack(push,1)
> +#pragma pack(push, 1)
> /*
> * Message types in the synthetic input protocol
> */
Perhaps it's better and more consistent with
other kernel style uses to remove #pragma pack[...]
and mark the individual structs with __packed;
$ grep -rP --include=*.[ch] "pragma.*pack" * | wc -l
221
$ grep -rP --include=*.[ch] "(__attribute__.*packed|\b__packed\b)" * | wc -l
5553
^ permalink raw reply
* [PATCH] drivers/virt: add missing linux/interrupt.h to fsl_hypervisor.c
From: Timur Tabi @ 2011-07-19 20:45 UTC (permalink / raw)
To: kumar.gala, linuxppc-dev, virtualization
fsl_hypervisor.c calls request_irq() but does not include linux/interrupt.h.
Normally, the driver will compile without error, but it can fail on some
configurations.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
drivers/virt/fsl_hypervisor.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/drivers/virt/fsl_hypervisor.c b/drivers/virt/fsl_hypervisor.c
index 1d3b8eb..3d91621 100644
--- a/drivers/virt/fsl_hypervisor.c
+++ b/drivers/virt/fsl_hypervisor.c
@@ -37,6 +37,7 @@
#include <linux/reboot.h>
#include <linux/uaccess.h>
#include <linux/notifier.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <asm/fsl_hcalls.h>
--
1.7.3.4
^ permalink raw reply related
* RE: [PATCH 5/8] Staging: hv: mousevsc: Fix checkpatch errors and warnings
From: KY Srinivasan @ 2011-07-19 22:46 UTC (permalink / raw)
To: Joe Perches
Cc: gregkh@suse.de, linux-kernel@vger.kernel.org,
devel@linuxdriverproject.org, virtualization@lists.osdl.org,
Haiyang Zhang
In-Reply-To: <1311103713.12882.13.camel@Joe-Laptop>
> -----Original Message-----
> From: Joe Perches [mailto:joe@perches.com]
> Sent: Tuesday, July 19, 2011 3:29 PM
> To: KY Srinivasan
> Cc: gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; virtualization@lists.osdl.org; Haiyang Zhang
> Subject: Re: [PATCH 5/8] Staging: hv: mousevsc: Fix checkpatch errors and
> warnings
>
> On Tue, 2011-07-19 at 11:44 -0700, K. Y. Srinivasan wrote:
> > Fix checkpatch errors and warnings.
> []
> > diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c
> []
> > @@ -53,7 +53,7 @@ struct hv_input_dev_info {
> > -#pragma pack(push,1)
> > +#pragma pack(push, 1)
> > /*
> > * Message types in the synthetic input protocol
> > */
>
> Perhaps it's better and more consistent with
> other kernel style uses to remove #pragma pack[...]
> and mark the individual structs with __packed;
Good point. Currently, this driver is not functional. When the driver
is finally functional, there is a whole lot of cleanup that is needed and I will
do what you are suggesting then. For this go around, I just wanted to address
checkpatch issues with minimal change.
Regards,
K. Y
^ permalink raw reply
* [PATCH repost] Fix panic in virtnet_remove
From: Krishna Kumar @ 2011-07-20 13:56 UTC (permalink / raw)
To: Rusty Russell, Michael S. Tsirkin
Cc: Krishna Kumar, netdev, linux-kernel, virtualization
Fix a panic in virtnet_remove. unregister_netdev has already
freed up the netdev (and virtnet_info) due to dev->destructor
being set, while virtnet_info is still required. Remove
virtnet_free altogether, and move the freeing of the per-cpu
statistics from virtnet_free to virtnet_remove.
Tested patch below.
Signed-off-by: Krishna Kumar <krkumar2@in.ibm.com>
---
(Michael suggested me to re-post with copy to all maintainers)
drivers/net/virtio_net.c | 10 +---------
1 file changed, 1 insertion(+), 9 deletions(-)
diff -ruNp org/drivers/net/virtio_net.c new/drivers/net/virtio_net.c
--- org/drivers/net/virtio_net.c 2011-07-18 09:14:02.000000000 +0530
+++ new/drivers/net/virtio_net.c 2011-07-18 09:16:35.000000000 +0530
@@ -705,14 +705,6 @@ static void virtnet_netpoll(struct net_d
}
#endif
-static void virtnet_free(struct net_device *dev)
-{
- struct virtnet_info *vi = netdev_priv(dev);
-
- free_percpu(vi->stats);
- free_netdev(dev);
-}
-
static int virtnet_open(struct net_device *dev)
{
struct virtnet_info *vi = netdev_priv(dev);
@@ -959,7 +951,6 @@ static int virtnet_probe(struct virtio_d
/* Set up network device as normal. */
dev->netdev_ops = &virtnet_netdev;
dev->features = NETIF_F_HIGHDMA;
- dev->destructor = virtnet_free;
SET_ETHTOOL_OPS(dev, &virtnet_ethtool_ops);
SET_NETDEV_DEV(dev, &vdev->dev);
@@ -1122,6 +1113,7 @@ static void __devexit virtnet_remove(str
while (vi->pages)
__free_pages(get_a_page(vi, GFP_KERNEL), 0);
+ free_percpu(vi->stats);
free_netdev(vi->dev);
}
^ permalink raw reply
* Re: [PATCH repost] Fix panic in virtnet_remove
From: Michael S. Tsirkin @ 2011-07-20 14:31 UTC (permalink / raw)
To: Krishna Kumar; +Cc: netdev, shemminger, linux-kernel, virtualization
In-Reply-To: <20110720135602.18705.21405.sendpatchset@krkumar2.in.ibm.com>
On Wed, Jul 20, 2011 at 07:26:02PM +0530, Krishna Kumar wrote:
> Fix a panic in virtnet_remove. unregister_netdev has already
> freed up the netdev (and virtnet_info) due to dev->destructor
> being set, while virtnet_info is still required. Remove
> virtnet_free altogether, and move the freeing of the per-cpu
> statistics from virtnet_free to virtnet_remove.
>
> Tested patch below.
>
> Signed-off-by: Krishna Kumar <krkumar2@in.ibm.com>
Also note that the crash was apparently introduced by
3fa2a1df909482cc234524906e4bd30dee3514df in net-next,
so this is a net-next only patch.
Stephen, was there any special reason to free the memory
in the destructor like you did?
Acked-by: Michael S. Tsirkin <mst@redhat.com>
> ---
> (Michael suggested me to re-post with copy to all maintainers)
>
> drivers/net/virtio_net.c | 10 +---------
> 1 file changed, 1 insertion(+), 9 deletions(-)
>
> diff -ruNp org/drivers/net/virtio_net.c new/drivers/net/virtio_net.c
> --- org/drivers/net/virtio_net.c 2011-07-18 09:14:02.000000000 +0530
> +++ new/drivers/net/virtio_net.c 2011-07-18 09:16:35.000000000 +0530
> @@ -705,14 +705,6 @@ static void virtnet_netpoll(struct net_d
> }
> #endif
>
> -static void virtnet_free(struct net_device *dev)
> -{
> - struct virtnet_info *vi = netdev_priv(dev);
> -
> - free_percpu(vi->stats);
> - free_netdev(dev);
> -}
> -
> static int virtnet_open(struct net_device *dev)
> {
> struct virtnet_info *vi = netdev_priv(dev);
> @@ -959,7 +951,6 @@ static int virtnet_probe(struct virtio_d
> /* Set up network device as normal. */
> dev->netdev_ops = &virtnet_netdev;
> dev->features = NETIF_F_HIGHDMA;
> - dev->destructor = virtnet_free;
>
> SET_ETHTOOL_OPS(dev, &virtnet_ethtool_ops);
> SET_NETDEV_DEV(dev, &vdev->dev);
> @@ -1122,6 +1113,7 @@ static void __devexit virtnet_remove(str
> while (vi->pages)
> __free_pages(get_a_page(vi, GFP_KERNEL), 0);
>
> + free_percpu(vi->stats);
> free_netdev(vi->dev);
> }
>
^ permalink raw reply
* [PATCH 0/9] netvsc bug fixes and cleanups
From: Haiyang Zhang @ 2011-07-21 17:14 UTC (permalink / raw)
To: haiyangz, hjanssen, kys, v-abkane, gregkh, linux-kernel, devel,
vir
Fixed a set of bugs in netvsc module, and cleaned up some coding style issues.
Haiyang Zhang (9):
staging: hv: remove unnecessary includes in netvsc
staging: hv: add newline to log messages in netvsc
staging: hv: convert dev_<loglevel> to netdev_<loglevel> in netvsc
staging: hv: fix a kernel warning in netvsc_linkstatus_callback()
staging: hv: re-order the code in netvsc_probe()
staging: hv: fix counting of #outstanding-sends in failed sends
staging: hv: fix counting of available buffer slots when send fails
staging: hv: fix the return status of netvsc_start_xmit()
staging: hv: fix the page buffer when rndis data go across page
boundary
drivers/staging/hv/netvsc.c | 124 ++++++++++++++++++++-----------------
drivers/staging/hv/netvsc_drv.c | 46 +++++++-------
drivers/staging/hv/rndis_filter.c | 28 ++++++---
3 files changed, 111 insertions(+), 87 deletions(-)
^ permalink raw reply
* [PATCH 1/9] staging: hv: remove unnecessary includes in netvsc
From: Haiyang Zhang @ 2011-07-21 17:14 UTC (permalink / raw)
To: haiyangz, hjanssen, kys, v-abkane, gregkh, linux-kernel, devel,
vir
In-Reply-To: <1311268497-8671-1-git-send-email-haiyangz@microsoft.com>
hyperv.h is included by hyperv_net.h already, so no need to include it
again in these C files.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
drivers/staging/hv/netvsc.c | 1 -
drivers/staging/hv/netvsc_drv.c | 1 -
drivers/staging/hv/rndis_filter.c | 1 -
3 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index 16a80b1..c3cc880 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -29,7 +29,6 @@
#include <linux/io.h>
#include <linux/slab.h>
-#include "hyperv.h"
#include "hyperv_net.h"
diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
index 474c5f0..1325de4 100644
--- a/drivers/staging/hv/netvsc_drv.c
+++ b/drivers/staging/hv/netvsc_drv.c
@@ -38,7 +38,6 @@
#include <net/sock.h>
#include <net/pkt_sched.h>
-#include "hyperv.h"
#include "hyperv_net.h"
static const char *driver_name = "netvsc";
diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c
index 6db48b9..8416bf2 100644
--- a/drivers/staging/hv/rndis_filter.c
+++ b/drivers/staging/hv/rndis_filter.c
@@ -27,7 +27,6 @@
#include <linux/if_ether.h>
#include <linux/netdevice.h>
-#include "hyperv.h"
#include "hyperv_net.h"
--
1.6.3.2
^ permalink raw reply related
* [PATCH 2/9] staging: hv: add newline to log messages in netvsc
From: Haiyang Zhang @ 2011-07-21 17:14 UTC (permalink / raw)
To: haiyangz, hjanssen, kys, v-abkane, gregkh, linux-kernel, devel,
vir
In-Reply-To: <1311268497-8671-1-git-send-email-haiyangz@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
drivers/staging/hv/netvsc.c | 58 +++++++++++++++++++-------------------
drivers/staging/hv/netvsc_drv.c | 2 +-
2 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index c3cc880..0eda326 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -139,7 +139,7 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device)
*/
if (ret != 0) {
dev_err(&net_device->dev->device, "unable to send "
- "revoke receive buffer to netvsp");
+ "revoke receive buffer to netvsp\n");
return ret;
}
}
@@ -154,7 +154,7 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device)
*/
if (ret != 0) {
dev_err(&net_device->dev->device,
- "unable to teardown receive buffer's gpadl");
+ "unable to teardown receive buffer's gpadl\n");
return -ret;
}
net_device->recv_buf_gpadl_handle = 0;
@@ -186,7 +186,7 @@ static int netvsc_init_recv_buf(struct hv_device *device)
net_device = get_outbound_net_device(device);
if (!net_device) {
dev_err(&device->device, "unable to get net device..."
- "device being destroyed?");
+ "device being destroyed?\n");
return -ENODEV;
}
@@ -195,7 +195,7 @@ static int netvsc_init_recv_buf(struct hv_device *device)
get_order(net_device->recv_buf_size));
if (!net_device->recv_buf) {
dev_err(&device->device, "unable to allocate receive "
- "buffer of size %d", net_device->recv_buf_size);
+ "buffer of size %d\n", net_device->recv_buf_size);
ret = -ENOMEM;
goto cleanup;
}
@@ -210,7 +210,7 @@ static int netvsc_init_recv_buf(struct hv_device *device)
&net_device->recv_buf_gpadl_handle);
if (ret != 0) {
dev_err(&device->device,
- "unable to establish receive buffer's gpadl");
+ "unable to establish receive buffer's gpadl\n");
goto cleanup;
}
@@ -234,7 +234,7 @@ static int netvsc_init_recv_buf(struct hv_device *device)
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
if (ret != 0) {
dev_err(&device->device,
- "unable to send receive buffer's gpadl to netvsp");
+ "unable to send receive buffer's gpadl to netvsp\n");
goto cleanup;
}
@@ -246,7 +246,7 @@ static int netvsc_init_recv_buf(struct hv_device *device)
if (init_packet->msg.v1_msg.
send_recv_buf_complete.status != NVSP_STAT_SUCCESS) {
dev_err(&device->device, "Unable to complete receive buffer "
- "initialzation with NetVsp - status %d",
+ "initialzation with NetVsp - status %d\n",
init_packet->msg.v1_msg.
send_recv_buf_complete.status);
ret = -EINVAL;
@@ -302,7 +302,7 @@ static int netvsc_connect_vsp(struct hv_device *device)
net_device = get_outbound_net_device(device);
if (!net_device) {
dev_err(&device->device, "unable to get net device..."
- "device being destroyed?");
+ "device being destroyed?\n");
return -ENODEV;
}
@@ -401,7 +401,7 @@ int netvsc_device_remove(struct hv_device *device)
/* Wait for all send completions */
while (atomic_read(&net_device->num_outstanding_sends)) {
dev_err(&device->device,
- "waiting for %d requests to complete...",
+ "waiting for %d requests to complete...\n",
atomic_read(&net_device->num_outstanding_sends));
udelay(100);
}
@@ -425,7 +425,7 @@ int netvsc_device_remove(struct hv_device *device)
udelay(100);
/* At this point, no one should be accessing netDevice except in here */
- dev_notice(&device->device, "net device safe to remove");
+ dev_notice(&device->device, "net device safe to remove\n");
/* Now, we can close the channel safely */
vmbus_close(device->channel);
@@ -451,7 +451,7 @@ static void netvsc_send_completion(struct hv_device *device,
net_device = get_inbound_net_device(device);
if (!net_device) {
dev_err(&device->device, "unable to get net device..."
- "device being destroyed?");
+ "device being destroyed?\n");
return;
}
@@ -480,7 +480,7 @@ static void netvsc_send_completion(struct hv_device *device,
atomic_dec(&net_device->num_outstanding_sends);
} else {
dev_err(&device->device, "Unknown send completion packet type- "
- "%d received!!", nvsp_packet->hdr.msg_type);
+ "%d received!!\n", nvsp_packet->hdr.msg_type);
}
put_net_device(device);
@@ -497,7 +497,7 @@ int netvsc_send(struct hv_device *device,
net_device = get_outbound_net_device(device);
if (!net_device) {
dev_err(&device->device, "net device (%p) shutting down..."
- "ignoring outbound packets", net_device);
+ "ignoring outbound packets\n", net_device);
return -ENODEV;
}
@@ -532,7 +532,7 @@ int netvsc_send(struct hv_device *device,
}
if (ret != 0)
- dev_err(&device->device, "Unable to send packet %p ret %d",
+ dev_err(&device->device, "Unable to send packet %p ret %d\n",
packet, ret);
atomic_inc(&net_device->num_outstanding_sends);
@@ -566,19 +566,19 @@ retry_send_cmplt:
/* no more room...wait a bit and attempt to retry 3 times */
retries++;
dev_err(&device->device, "unable to send receive completion pkt"
- " (tid %llx)...retrying %d", transaction_id, retries);
+ " (tid %llx)...retrying %d\n", transaction_id, retries);
if (retries < 4) {
udelay(100);
goto retry_send_cmplt;
} else {
dev_err(&device->device, "unable to send receive "
- "completion pkt (tid %llx)...give up retrying",
+ "completion pkt (tid %llx)...give up retrying\n",
transaction_id);
}
} else {
dev_err(&device->device, "unable to send receive "
- "completion pkt - %llx", transaction_id);
+ "completion pkt - %llx\n", transaction_id);
}
}
@@ -600,7 +600,7 @@ static void netvsc_receive_completion(void *context)
net_device = get_inbound_net_device(device);
if (!net_device) {
dev_err(&device->device, "unable to get net device..."
- "device being destroyed?");
+ "device being destroyed?\n");
return;
}
@@ -652,7 +652,7 @@ static void netvsc_receive(struct hv_device *device,
net_device = get_inbound_net_device(device);
if (!net_device) {
dev_err(&device->device, "unable to get net device..."
- "device being destroyed?");
+ "device being destroyed?\n");
return;
}
@@ -661,7 +661,7 @@ static void netvsc_receive(struct hv_device *device,
* packet
*/
if (packet->type != VM_PKT_DATA_USING_XFER_PAGES) {
- dev_err(&device->device, "Unknown packet type received - %d",
+ dev_err(&device->device, "Unknown packet type received - %d\n",
packet->type);
put_net_device(device);
return;
@@ -674,7 +674,7 @@ static void netvsc_receive(struct hv_device *device,
if (nvsp_packet->hdr.msg_type !=
NVSP_MSG1_TYPE_SEND_RNDIS_PKT) {
dev_err(&device->device, "Unknown nvsp packet type received-"
- " %d", nvsp_packet->hdr.msg_type);
+ " %d\n", nvsp_packet->hdr.msg_type);
put_net_device(device);
return;
}
@@ -683,7 +683,7 @@ static void netvsc_receive(struct hv_device *device,
if (vmxferpage_packet->xfer_pageset_id != NETVSC_RECEIVE_BUFFER_ID) {
dev_err(&device->device, "Invalid xfer page set id - "
- "expecting %x got %x", NETVSC_RECEIVE_BUFFER_ID,
+ "expecting %x got %x\n", NETVSC_RECEIVE_BUFFER_ID,
vmxferpage_packet->xfer_pageset_id);
put_net_device(device);
return;
@@ -710,7 +710,7 @@ static void netvsc_receive(struct hv_device *device,
*/
if (count < 2) {
dev_err(&device->device, "Got only %d netvsc pkt...needed "
- "%d pkts. Dropping this xfer page packet completely!",
+ "%d pkts. Dropping this xfer page packet completely!\n",
count, vmxferpage_packet->range_cnt + 1);
/* Return it to the freelist */
@@ -738,7 +738,7 @@ static void netvsc_receive(struct hv_device *device,
if (xferpage_packet->count != vmxferpage_packet->range_cnt) {
dev_err(&device->device, "Needed %d netvsc pkts to satisy "
- "this xfer page...got %d",
+ "this xfer page...got %d\n",
vmxferpage_packet->range_cnt, xferpage_packet->count);
}
@@ -837,7 +837,7 @@ static void netvsc_channel_cb(void *context)
net_device = get_inbound_net_device(device);
if (!net_device) {
dev_err(&device->device, "net device (%p) shutting down..."
- "ignoring inbound packets", net_device);
+ "ignoring inbound packets\n", net_device);
goto out;
}
@@ -888,7 +888,7 @@ static void netvsc_channel_cb(void *context)
/* Try again next time around */
dev_err(&device->device,
"unable to allocate buffer of size "
- "(%d)!!", bytes_recvd);
+ "(%d)!!\n", bytes_recvd);
break;
}
@@ -945,18 +945,18 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
netvsc_channel_cb, device);
if (ret != 0) {
- dev_err(&device->device, "unable to open channel: %d", ret);
+ dev_err(&device->device, "unable to open channel: %d\n", ret);
goto cleanup;
}
/* Channel is opened */
- pr_info("hv_netvsc channel opened successfully");
+ pr_info("hv_netvsc channel opened successfully\n");
/* Connect with the NetVsp */
ret = netvsc_connect_vsp(device);
if (ret != 0) {
dev_err(&device->device,
- "unable to connect to NetVSP - %d", ret);
+ "unable to connect to NetVSP - %d\n", ret);
goto close;
}
diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
index 1325de4..7b9d9ca 100644
--- a/drivers/staging/hv/netvsc_drv.c
+++ b/drivers/staging/hv/netvsc_drv.c
@@ -446,7 +446,7 @@ static int __init netvsc_drv_init(void)
struct hv_driver *drv = &netvsc_drv;
int ret;
- pr_info("initializing....");
+ pr_info("initializing....\n");
drv->driver.name = driver_name;
--
1.6.3.2
^ permalink raw reply related
* [PATCH 3/9] staging: hv: convert dev_<loglevel> to netdev_<loglevel> in netvsc
From: Haiyang Zhang @ 2011-07-21 17:14 UTC (permalink / raw)
To: haiyangz, hjanssen, kys, v-abkane, gregkh, linux-kernel, devel,
vir
In-Reply-To: <1311268497-8671-1-git-send-email-haiyangz@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
drivers/staging/hv/netvsc.c | 68 +++++++++++++++++++++----------------
drivers/staging/hv/rndis_filter.c | 17 +++++----
2 files changed, 49 insertions(+), 36 deletions(-)
diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index 0eda326..159c490 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -28,6 +28,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/slab.h>
+#include <linux/netdevice.h>
#include "hyperv_net.h"
@@ -111,6 +112,7 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device)
{
struct nvsp_message *revoke_packet;
int ret = 0;
+ struct net_device *ndev = dev_get_drvdata(&net_device->dev->device);
/*
* If we got a section count, it means we received a
@@ -138,7 +140,7 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device)
* have a leak rather than continue and a bugchk
*/
if (ret != 0) {
- dev_err(&net_device->dev->device, "unable to send "
+ netdev_err(ndev, "unable to send "
"revoke receive buffer to netvsp\n");
return ret;
}
@@ -153,7 +155,7 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device)
* rather than continue and a bugchk
*/
if (ret != 0) {
- dev_err(&net_device->dev->device,
+ netdev_err(ndev,
"unable to teardown receive buffer's gpadl\n");
return -ret;
}
@@ -182,10 +184,11 @@ static int netvsc_init_recv_buf(struct hv_device *device)
int t;
struct netvsc_device *net_device;
struct nvsp_message *init_packet;
+ struct net_device *ndev = dev_get_drvdata(&device->device);
net_device = get_outbound_net_device(device);
if (!net_device) {
- dev_err(&device->device, "unable to get net device..."
+ netdev_err(ndev, "unable to get net device..."
"device being destroyed?\n");
return -ENODEV;
}
@@ -194,7 +197,7 @@ static int netvsc_init_recv_buf(struct hv_device *device)
(void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
get_order(net_device->recv_buf_size));
if (!net_device->recv_buf) {
- dev_err(&device->device, "unable to allocate receive "
+ netdev_err(ndev, "unable to allocate receive "
"buffer of size %d\n", net_device->recv_buf_size);
ret = -ENOMEM;
goto cleanup;
@@ -209,7 +212,7 @@ static int netvsc_init_recv_buf(struct hv_device *device)
net_device->recv_buf_size,
&net_device->recv_buf_gpadl_handle);
if (ret != 0) {
- dev_err(&device->device,
+ netdev_err(ndev,
"unable to establish receive buffer's gpadl\n");
goto cleanup;
}
@@ -233,7 +236,7 @@ static int netvsc_init_recv_buf(struct hv_device *device)
VM_PKT_DATA_INBAND,
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
if (ret != 0) {
- dev_err(&device->device,
+ netdev_err(ndev,
"unable to send receive buffer's gpadl to netvsp\n");
goto cleanup;
}
@@ -245,7 +248,7 @@ static int netvsc_init_recv_buf(struct hv_device *device)
/* Check the response */
if (init_packet->msg.v1_msg.
send_recv_buf_complete.status != NVSP_STAT_SUCCESS) {
- dev_err(&device->device, "Unable to complete receive buffer "
+ netdev_err(ndev, "Unable to complete receive buffer "
"initialzation with NetVsp - status %d\n",
init_packet->msg.v1_msg.
send_recv_buf_complete.status);
@@ -298,10 +301,11 @@ static int netvsc_connect_vsp(struct hv_device *device)
struct netvsc_device *net_device;
struct nvsp_message *init_packet;
int ndis_version;
+ struct net_device *ndev = dev_get_drvdata(&device->device);
net_device = get_outbound_net_device(device);
if (!net_device) {
- dev_err(&device->device, "unable to get net device..."
+ netdev_err(ndev, "unable to get net device..."
"device being destroyed?\n");
return -ENODEV;
}
@@ -400,7 +404,7 @@ int netvsc_device_remove(struct hv_device *device)
/* Wait for all send completions */
while (atomic_read(&net_device->num_outstanding_sends)) {
- dev_err(&device->device,
+ dev_info(&device->device,
"waiting for %d requests to complete...\n",
atomic_read(&net_device->num_outstanding_sends));
udelay(100);
@@ -447,10 +451,11 @@ static void netvsc_send_completion(struct hv_device *device,
struct netvsc_device *net_device;
struct nvsp_message *nvsp_packet;
struct hv_netvsc_packet *nvsc_packet;
+ struct net_device *ndev = dev_get_drvdata(&device->device);
net_device = get_inbound_net_device(device);
if (!net_device) {
- dev_err(&device->device, "unable to get net device..."
+ netdev_err(ndev, "unable to get net device..."
"device being destroyed?\n");
return;
}
@@ -479,7 +484,7 @@ static void netvsc_send_completion(struct hv_device *device,
atomic_dec(&net_device->num_outstanding_sends);
} else {
- dev_err(&device->device, "Unknown send completion packet type- "
+ netdev_err(ndev, "Unknown send completion packet type- "
"%d received!!\n", nvsp_packet->hdr.msg_type);
}
@@ -491,12 +496,12 @@ int netvsc_send(struct hv_device *device,
{
struct netvsc_device *net_device;
int ret = 0;
-
struct nvsp_message sendMessage;
+ struct net_device *ndev = dev_get_drvdata(&device->device);
net_device = get_outbound_net_device(device);
if (!net_device) {
- dev_err(&device->device, "net device (%p) shutting down..."
+ netdev_err(ndev, "net device (%p) shutting down..."
"ignoring outbound packets\n", net_device);
return -ENODEV;
}
@@ -532,7 +537,7 @@ int netvsc_send(struct hv_device *device,
}
if (ret != 0)
- dev_err(&device->device, "Unable to send packet %p ret %d\n",
+ netdev_err(ndev, "Unable to send packet %p ret %d\n",
packet, ret);
atomic_inc(&net_device->num_outstanding_sends);
@@ -546,6 +551,7 @@ static void netvsc_send_recv_completion(struct hv_device *device,
struct nvsp_message recvcompMessage;
int retries = 0;
int ret;
+ struct net_device *ndev = dev_get_drvdata(&device->device);
recvcompMessage.hdr.msg_type =
NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE;
@@ -565,19 +571,19 @@ retry_send_cmplt:
} else if (ret == -EAGAIN) {
/* no more room...wait a bit and attempt to retry 3 times */
retries++;
- dev_err(&device->device, "unable to send receive completion pkt"
+ netdev_err(ndev, "unable to send receive completion pkt"
" (tid %llx)...retrying %d\n", transaction_id, retries);
if (retries < 4) {
udelay(100);
goto retry_send_cmplt;
} else {
- dev_err(&device->device, "unable to send receive "
+ netdev_err(ndev, "unable to send receive "
"completion pkt (tid %llx)...give up retrying\n",
transaction_id);
}
} else {
- dev_err(&device->device, "unable to send receive "
+ netdev_err(ndev, "unable to send receive "
"completion pkt - %llx\n", transaction_id);
}
}
@@ -591,6 +597,7 @@ static void netvsc_receive_completion(void *context)
u64 transaction_id = 0;
bool fsend_receive_comp = false;
unsigned long flags;
+ struct net_device *ndev = dev_get_drvdata(&device->device);
/*
* Even though it seems logical to do a GetOutboundNetDevice() here to
@@ -599,7 +606,7 @@ static void netvsc_receive_completion(void *context)
*/
net_device = get_inbound_net_device(device);
if (!net_device) {
- dev_err(&device->device, "unable to get net device..."
+ netdev_err(ndev, "unable to get net device..."
"device being destroyed?\n");
return;
}
@@ -646,12 +653,13 @@ static void netvsc_receive(struct hv_device *device,
int i, j;
int count = 0, bytes_remain = 0;
unsigned long flags;
+ struct net_device *ndev = dev_get_drvdata(&device->device);
LIST_HEAD(listHead);
net_device = get_inbound_net_device(device);
if (!net_device) {
- dev_err(&device->device, "unable to get net device..."
+ netdev_err(ndev, "unable to get net device..."
"device being destroyed?\n");
return;
}
@@ -661,7 +669,7 @@ static void netvsc_receive(struct hv_device *device,
* packet
*/
if (packet->type != VM_PKT_DATA_USING_XFER_PAGES) {
- dev_err(&device->device, "Unknown packet type received - %d\n",
+ netdev_err(ndev, "Unknown packet type received - %d\n",
packet->type);
put_net_device(device);
return;
@@ -673,7 +681,7 @@ static void netvsc_receive(struct hv_device *device,
/* Make sure this is a valid nvsp packet */
if (nvsp_packet->hdr.msg_type !=
NVSP_MSG1_TYPE_SEND_RNDIS_PKT) {
- dev_err(&device->device, "Unknown nvsp packet type received-"
+ netdev_err(ndev, "Unknown nvsp packet type received-"
" %d\n", nvsp_packet->hdr.msg_type);
put_net_device(device);
return;
@@ -682,7 +690,7 @@ static void netvsc_receive(struct hv_device *device,
vmxferpage_packet = (struct vmtransfer_page_packet_header *)packet;
if (vmxferpage_packet->xfer_pageset_id != NETVSC_RECEIVE_BUFFER_ID) {
- dev_err(&device->device, "Invalid xfer page set id - "
+ netdev_err(ndev, "Invalid xfer page set id - "
"expecting %x got %x\n", NETVSC_RECEIVE_BUFFER_ID,
vmxferpage_packet->xfer_pageset_id);
put_net_device(device);
@@ -709,7 +717,7 @@ static void netvsc_receive(struct hv_device *device,
* some of the xfer page packet ranges...
*/
if (count < 2) {
- dev_err(&device->device, "Got only %d netvsc pkt...needed "
+ netdev_err(ndev, "Got only %d netvsc pkt...needed "
"%d pkts. Dropping this xfer page packet completely!\n",
count, vmxferpage_packet->range_cnt + 1);
@@ -737,7 +745,7 @@ static void netvsc_receive(struct hv_device *device,
xferpage_packet->count = count - 1;
if (xferpage_packet->count != vmxferpage_packet->range_cnt) {
- dev_err(&device->device, "Needed %d netvsc pkts to satisy "
+ netdev_err(ndev, "Needed %d netvsc pkts to satisy "
"this xfer page...got %d\n",
vmxferpage_packet->range_cnt, xferpage_packet->count);
}
@@ -827,6 +835,7 @@ static void netvsc_channel_cb(void *context)
struct vmpacket_descriptor *desc;
unsigned char *buffer;
int bufferlen = NETVSC_PACKET_SIZE;
+ struct net_device *ndev = dev_get_drvdata(&device->device);
packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char),
GFP_ATOMIC);
@@ -836,7 +845,7 @@ static void netvsc_channel_cb(void *context)
net_device = get_inbound_net_device(device);
if (!net_device) {
- dev_err(&device->device, "net device (%p) shutting down..."
+ netdev_err(ndev, "net device (%p) shutting down..."
"ignoring inbound packets\n", net_device);
goto out;
}
@@ -857,7 +866,7 @@ static void netvsc_channel_cb(void *context)
break;
default:
- dev_err(&device->device,
+ netdev_err(ndev,
"unhandled packet type %d, "
"tid %llx len %d\n",
desc->type, request_id,
@@ -886,7 +895,7 @@ static void netvsc_channel_cb(void *context)
buffer = kmalloc(bytes_recvd, GFP_ATOMIC);
if (buffer == NULL) {
/* Try again next time around */
- dev_err(&device->device,
+ netdev_err(ndev,
"unable to allocate buffer of size "
"(%d)!!\n", bytes_recvd);
break;
@@ -914,6 +923,7 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
((struct netvsc_device_info *)additional_info)->ring_size;
struct netvsc_device *net_device;
struct hv_netvsc_packet *packet, *pos;
+ struct net_device *ndev = dev_get_drvdata(&device->device);
net_device = alloc_net_device(device);
if (!net_device) {
@@ -945,7 +955,7 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
netvsc_channel_cb, device);
if (ret != 0) {
- dev_err(&device->device, "unable to open channel: %d\n", ret);
+ netdev_err(ndev, "unable to open channel: %d\n", ret);
goto cleanup;
}
@@ -955,7 +965,7 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
/* Connect with the NetVsp */
ret = netvsc_connect_vsp(device);
if (ret != 0) {
- dev_err(&device->device,
+ netdev_err(ndev,
"unable to connect to NetVSP - %d\n", ret);
goto close;
}
diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c
index 8416bf2..20e673d 100644
--- a/drivers/staging/hv/rndis_filter.c
+++ b/drivers/staging/hv/rndis_filter.c
@@ -249,6 +249,7 @@ static void rndis_filter_receive_response(struct rndis_device *dev,
struct rndis_request *request = NULL;
bool found = false;
unsigned long flags;
+ struct net_device *ndev = dev_get_drvdata(&dev->net_dev->dev->device);
spin_lock_irqsave(&dev->request_lock, flags);
list_for_each_entry(request, &dev->req_list, list_ent) {
@@ -269,7 +270,7 @@ static void rndis_filter_receive_response(struct rndis_device *dev,
memcpy(&request->response_msg, resp,
resp->msg_len);
} else {
- dev_err(&dev->net_dev->dev->device,
+ netdev_err(ndev,
"rndis response buffer overflow "
"detected (size %u max %zu)\n",
resp->msg_len,
@@ -289,7 +290,7 @@ static void rndis_filter_receive_response(struct rndis_device *dev,
complete(&request->wait_event);
} else {
- dev_err(&dev->net_dev->dev->device,
+ netdev_err(ndev,
"no rndis request found for this response "
"(id 0x%x res type 0x%x)\n",
resp->msg.init_complete.req_id,
@@ -349,20 +350,21 @@ int rndis_filter_receive(struct hv_device *dev,
struct rndis_device *rndis_dev;
struct rndis_message rndis_msg;
struct rndis_message *rndis_hdr;
+ struct net_device *ndev = dev_get_drvdata(&dev->device);
if (!net_dev)
return -EINVAL;
/* Make sure the rndis device state is initialized */
if (!net_dev->extension) {
- dev_err(&dev->device, "got rndis message but no rndis device - "
+ netdev_err(ndev, "got rndis message but no rndis device - "
"dropping this message!\n");
return -ENODEV;
}
rndis_dev = (struct rndis_device *)net_dev->extension;
if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
- dev_err(&dev->device, "got rndis message but rndis device "
+ netdev_err(ndev, "got rndis message but rndis device "
"uninitialized...dropping this message!\n");
return -ENODEV;
}
@@ -376,7 +378,7 @@ int rndis_filter_receive(struct hv_device *dev,
/* Make sure we got a valid rndis message */
if ((rndis_hdr->ndis_msg_type != REMOTE_NDIS_PACKET_MSG) &&
(rndis_hdr->msg_len > sizeof(struct rndis_message))) {
- dev_err(&dev->device, "incoming rndis message buffer overflow "
+ netdev_err(ndev, "incoming rndis message buffer overflow "
"detected (got %u, max %zu)..marking it an error!\n",
rndis_hdr->msg_len,
sizeof(struct rndis_message));
@@ -409,7 +411,7 @@ int rndis_filter_receive(struct hv_device *dev,
rndis_filter_receive_indicate_status(rndis_dev, &rndis_msg);
break;
default:
- dev_err(&dev->device,
+ netdev_err(ndev,
"unhandled rndis message (type %u len %u)\n",
rndis_msg.ndis_msg_type,
rndis_msg.msg_len);
@@ -505,6 +507,7 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev,
struct rndis_set_complete *set_complete;
u32 status;
int ret, t;
+ struct net_device *ndev = dev_get_drvdata(&dev->net_dev->dev->device);
request = get_rndis_request(dev, REMOTE_NDIS_SET_MSG,
RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
@@ -530,7 +533,7 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev,
t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
if (t == 0) {
- dev_err(&dev->net_dev->dev->device,
+ netdev_err(ndev,
"timeout before we got a set response...\n");
/*
* We can't deallocate the request since we may still receive a
--
1.6.3.2
^ permalink raw reply related
* [PATCH 4/9] staging: hv: fix a kernel warning in netvsc_linkstatus_callback()
From: Haiyang Zhang @ 2011-07-21 17:14 UTC (permalink / raw)
To: haiyangz, hjanssen, kys, v-abkane, gregkh, linux-kernel, devel,
vir; +Cc: stable
In-Reply-To: <1311268497-8671-1-git-send-email-haiyangz@microsoft.com>
netif_notify_peers() caused a kernel warning in netvsc_linkstatus_callback(),
because netvsc_linkstatus_callback() is within IRQ context. So we move
the first call to netif_notify_peers() into queued work as well, but with
zero delay.
In addition to "staging-next", this should also be back-ported to stable
kernels 2.6.32 and later.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Cc: stable <stable@kernel.org>
---
drivers/staging/hv/netvsc_drv.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
index 7b9d9ca..c8e2f24 100644
--- a/drivers/staging/hv/netvsc_drv.c
+++ b/drivers/staging/hv/netvsc_drv.c
@@ -216,8 +216,8 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
if (status == 1) {
netif_carrier_on(net);
netif_wake_queue(net);
- netif_notify_peers(net);
ndev_ctx = netdev_priv(net);
+ schedule_delayed_work(&ndev_ctx->dwork, 0);
schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
} else {
netif_carrier_off(net);
--
1.6.3.2
^ permalink raw reply related
* [PATCH 5/9] staging: hv: re-order the code in netvsc_probe()
From: Haiyang Zhang @ 2011-07-21 17:14 UTC (permalink / raw)
To: haiyangz, hjanssen, kys, v-abkane, gregkh, linux-kernel, devel,
vir
In-Reply-To: <1311268497-8671-1-git-send-email-haiyangz@microsoft.com>
Re-order the code in netvsc_probe() to prevent a guest crash caused by
packets possibly received from NetVSP before call to register_netdev().
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
drivers/staging/hv/netvsc_drv.c | 32 +++++++++++++++++---------------
1 files changed, 17 insertions(+), 15 deletions(-)
diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
index c8e2f24..816e382 100644
--- a/drivers/staging/hv/netvsc_drv.c
+++ b/drivers/staging/hv/netvsc_drv.c
@@ -350,19 +350,6 @@ static int netvsc_probe(struct hv_device *dev)
dev_set_drvdata(&dev->device, net);
INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp);
- /* Notify the netvsc driver of the new device */
- device_info.ring_size = ring_size;
- ret = rndis_filter_device_add(dev, &device_info);
- if (ret != 0) {
- free_netdev(net);
- dev_set_drvdata(&dev->device, NULL);
- return ret;
- }
-
- netif_carrier_on(net);
-
- memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
-
net->netdev_ops = &device_ops;
/* TODO: Add GSO and Checksum offload */
@@ -374,11 +361,26 @@ static int netvsc_probe(struct hv_device *dev)
ret = register_netdev(net);
if (ret != 0) {
- /* Remove the device and release the resource */
- rndis_filter_device_remove(dev);
+ pr_err("Unable to register netdev.\n");
free_netdev(net);
+ goto out;
}
+ /* Notify the netvsc driver of the new device */
+ device_info.ring_size = ring_size;
+ ret = rndis_filter_device_add(dev, &device_info);
+ if (ret != 0) {
+ netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
+ unregister_netdev(net);
+ free_netdev(net);
+ dev_set_drvdata(&dev->device, NULL);
+ return ret;
+ }
+ memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
+
+ netif_carrier_on(net);
+
+out:
return ret;
}
--
1.6.3.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox