From 3423a33331233a13c7afc0d1f6187f98f904b821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Fri, 17 Dec 2010 11:40:24 +0200 Subject: [PATCH 1/4] staging: hv: fix netvsc sleeping while atomic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BugLink: http://bugs.launchpad.net/bugs/752064 The channel callbacks are called directly from vmbus_event_dpc which runs in tasklet context. These callbacks need to use GFP_ATOMIC. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=16701 Cc: Hank Janssen Cc: Haiyang Zhang Signed-off-by: Timo Teräs Cc: stable Signed-off-by: Greg Kroah-Hartman (cherry picked from commit d70c673153d42e8aefd5ac296c8159ef222d076b) Signed-off-by: Tim Gardner --- drivers/staging/hv/netvsc.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index ba15059..7fd2adc 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -1313,7 +1313,7 @@ static void NetVscOnChannelCallback(void *Context) /* ASSERT(device); */ packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char), - GFP_KERNEL); + GFP_ATOMIC); if (!packet) return; buffer = packet; -- 1.7.0.4 From 7fe809a4fdf610cfad2fb5318bfc1e89cb2eac89 Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Fri, 18 Feb 2011 15:05:53 -0800 Subject: [PATCH 2/4] staging: hv: Fix the WARN_ON condition in free_net_device() BugLink: http://bugs.launchpad.net/bugs/752064 In a previous commit, 7a09876d, ASSERT was changed to WARN_ON, but the condition wasn't updated. This patch fixed this error. Signed-off-by: Haiyang Zhang Signed-off-by: K. Y. Srinivasan Signed-off-by: Hank Janssen Signed-off-by: Greg Kroah-Hartman backported from 31acaa50c6c61bfb486dacaa2ec62950a42de233 Signed-off-by: Tim Gardner --- drivers/staging/hv/netvsc.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index 7fd2adc..3be3a57 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -92,7 +92,7 @@ static struct netvsc_device *AllocNetDevice(struct hv_device *Device) static void FreeNetDevice(struct netvsc_device *Device) { - WARN_ON(atomic_read(&Device->RefCount) == 0); + WARN_ON(atomic_read(&Device->RefCount) != 0); Device->Device->Extension = NULL; kfree(Device); } -- 1.7.0.4 From bc4d9acc00595509bdc5bd48ebd9adee04f99adf Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Thu, 7 Apr 2011 06:58:48 -0600 Subject: [PATCH 3/4] UBUNTU: SAUCE: staging: hv: Fixed issue with scheduling while atomic in hv_vmbus BugLink: http://bugs.launchpad.net/bugs/752064 Allocate callback structure memory using GFP_ATOMIC. Signed-off-by: Hank Janssen Signed-off-by: Tim Gardner --- drivers/staging/hv/osd.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/staging/hv/osd.c b/drivers/staging/hv/osd.c index 8c3eb27..eb9b20d 100644 --- a/drivers/staging/hv/osd.c +++ b/drivers/staging/hv/osd.c @@ -214,7 +214,7 @@ int osd_schedule_callback(struct workqueue_struct *wq, { struct osd_callback_struct *cb; - cb = kmalloc(sizeof(*cb), GFP_KERNEL); + cb = kmalloc(sizeof(*cb), GFP_ATOMIC); if (!cb) { printk(KERN_ERR "unable to allocate memory in osd_schedule_callback\n"); return -1; -- 1.7.0.4 From c8f1449119d007482a7fcfade180addf42ab939f Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Thu, 7 Apr 2011 07:03:20 -0600 Subject: [PATCH 4/4] UBUNTU: SAUCE: Backport of mainline loss of network fix for Hyper-V BugLink: http://bugs.launchpad.net/bugs/752064 In some scenarios you lose network connectivity with Hyper-V. This fix solves that problem. It is a backported fix from mainline by Olaf Hering Since there are too many code differences from mainline and 2.6.35, I created this new patch. Locking is required when tweaking bits located in a shared page, use the sync_version of bitops. Without this change vmbus_on_event() will miss events and as a result, vmbus_isr() will not schedule the receive tasklet. Thanks to Mike Surcouf for testing this. Signed-off-by: Hank Janssen Signed-off-by: Haiyang Zhang Signed-off-by: K. Y. Srinivasan Tested-by: Mike Surcouf Cc: Olaf Hering Signed-off-by: Tim Gardner --- drivers/staging/hv/channel.c | 8 ++++---- drivers/staging/hv/connection.c | 4 ++-- drivers/staging/hv/vmbus.c | 2 +- drivers/staging/hv/vmbus_private.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/hv/channel.c b/drivers/staging/hv/channel.c index f047c5a..8955d6a 100644 --- a/drivers/staging/hv/channel.c +++ b/drivers/staging/hv/channel.c @@ -78,14 +78,14 @@ static void VmbusChannelSetEvent(struct vmbus_channel *Channel) if (Channel->OfferMsg.MonitorAllocated) { /* Each u32 represents 32 channels */ - set_bit(Channel->OfferMsg.ChildRelId & 31, + sync_set_bit(Channel->OfferMsg.ChildRelId & 31, (unsigned long *) gVmbusConnection.SendInterruptPage + (Channel->OfferMsg.ChildRelId >> 5)); monitorPage = gVmbusConnection.MonitorPages; monitorPage++; /* Get the child to parent monitor page */ - set_bit(Channel->MonitorBit, + sync_set_bit(Channel->MonitorBit, (unsigned long *)&monitorPage->TriggerGroup [Channel->MonitorGroup].Pending); @@ -105,7 +105,7 @@ static void VmbusChannelClearEvent(struct vmbus_channel *channel) if (Channel->OfferMsg.MonitorAllocated) { /* Each u32 represents 32 channels */ - clear_bit(Channel->OfferMsg.ChildRelId & 31, + sync_clear_bit(Channel->OfferMsg.ChildRelId & 31, (unsigned long *)gVmbusConnection.SendInterruptPage + (Channel->OfferMsg.ChildRelId >> 5)); @@ -113,7 +113,7 @@ static void VmbusChannelClearEvent(struct vmbus_channel *channel) (struct hv_monitor_page *)gVmbusConnection.MonitorPages; monitorPage++; /* Get the child to parent monitor page */ - clear_bit(Channel->MonitorBit, + sync_clear_bit(Channel->MonitorBit, (unsigned long *)&monitorPage->TriggerGroup [Channel->MonitorGroup].Pending); } diff --git a/drivers/staging/hv/connection.c b/drivers/staging/hv/connection.c index e8824da..82a2cb0 100644 --- a/drivers/staging/hv/connection.c +++ b/drivers/staging/hv/connection.c @@ -292,7 +292,7 @@ void VmbusOnEvents(void) for (dword = 0; dword < maxdword; dword++) { if (recvInterruptPage[dword]) { for (bit = 0; bit < 32; bit++) { - if (test_and_clear_bit(bit, (unsigned long *)&recvInterruptPage[dword])) { + if (sync_test_and_clear_bit(bit, (unsigned long *)&recvInterruptPage[dword])) { relid = (dword << 5) + bit; DPRINT_DBG(VMBUS, "event detected for relid - %d", relid); @@ -337,7 +337,7 @@ int VmbusSetEvent(u32 childRelId) DPRINT_ENTER(VMBUS); /* Each u32 represents 32 channels */ - set_bit(childRelId & 31, + sync_set_bit(childRelId & 31, (unsigned long *)gVmbusConnection.SendInterruptPage + (childRelId >> 5)); diff --git a/drivers/staging/hv/vmbus.c b/drivers/staging/hv/vmbus.c index 007543b..08a0c59 100644 --- a/drivers/staging/hv/vmbus.c +++ b/drivers/staging/hv/vmbus.c @@ -254,7 +254,7 @@ static int VmbusOnISR(struct hv_driver *drv) event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT; /* Since we are a child, we only need to check bit 0 */ - if (test_and_clear_bit(0, (unsigned long *) &event->Flags32[0])) { + if (sync_test_and_clear_bit(0, (unsigned long *) &event->Flags32[0])) { DPRINT_DBG(VMBUS, "received event %d", event->Flags32[0]); ret |= 0x2; } diff --git a/drivers/staging/hv/vmbus_private.h b/drivers/staging/hv/vmbus_private.h index 588c667..3e6c00a 100644 --- a/drivers/staging/hv/vmbus_private.h +++ b/drivers/staging/hv/vmbus_private.h @@ -32,7 +32,7 @@ #include "channel_interface.h" #include "ring_buffer.h" #include - +#include /* * Maximum channels is determined by the size of the interrupt page -- 1.7.0.4