Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755294AbbBOS5R (ORCPT ); Sun, 15 Feb 2015 13:57:17 -0500 Received: from p3plsmtps2ded01.prod.phx3.secureserver.net ([208.109.80.58]:54913 "EHLO p3plsmtps2ded01.prod.phx3.secureserver.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755232AbbBOS5P (ORCPT ); Sun, 15 Feb 2015 13:57:15 -0500 x-originating-ip: 72.167.245.219 From: "K. Y. Srinivasan" To: gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, devel@linuxdriverproject.org, olaf@aepfle.de, apw@canonical.com, vkuznets@redhat.com Cc: "K. Y. Srinivasan" Subject: [PATCH 3/6] Drivers: hv: vmbus: Handle both rescind and offer messages in the same context Date: Sun, 15 Feb 2015 12:11:37 -0800 Message-Id: <1424031100-21749-3-git-send-email-kys@microsoft.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1424031100-21749-1-git-send-email-kys@microsoft.com> References: <1424031079-21708-1-git-send-email-kys@microsoft.com> <1424031100-21749-1-git-send-email-kys@microsoft.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4553 Lines: 144 Execute both ressind and offer messages in the same work context. This serializes these operations and naturally addresses the various corner cases. Signed-off-by: K. Y. Srinivasan --- drivers/hv/channel_mgmt.c | 71 ++++++++++++-------------------------------- 1 files changed, 20 insertions(+), 51 deletions(-) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index b933891..af53168 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -244,29 +244,6 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) free_channel(channel); } -/* - * vmbus_process_rescind_offer - - * Rescind the offer by initiating a device removal - */ -static void vmbus_process_rescind_offer(struct work_struct *work) -{ - struct vmbus_channel *channel = container_of(work, - struct vmbus_channel, - work); - struct device *dev; - - if (channel->device_obj) { - dev = get_device(&channel->device_obj->device); - if (dev) { - vmbus_device_unregister(channel->device_obj); - put_device(dev); - } - } else { - hv_process_channel_removal(channel, - channel->offermsg.child_relid); - } -} - void vmbus_free_channels(void) { struct vmbus_channel *channel; @@ -281,11 +258,8 @@ void vmbus_free_channels(void) * vmbus_process_offer - Process the offer by creating a channel/device * associated with this offer */ -static void vmbus_process_offer(struct work_struct *work) +static void vmbus_process_offer(struct vmbus_channel *newchannel) { - struct vmbus_channel *newchannel = container_of(work, - struct vmbus_channel, - work); struct vmbus_channel *channel; bool fnew = true; bool enq = false; @@ -351,7 +325,7 @@ static void vmbus_process_offer(struct work_struct *work) if (channel->sc_creation_callback != NULL) channel->sc_creation_callback(newchannel); - goto done_init_rescind; + return; } goto err_free_chan; @@ -392,15 +366,9 @@ static void vmbus_process_offer(struct work_struct *work) kfree(newchannel->device_obj); goto err_free_chan; } -done_init_rescind: - spin_lock_irqsave(&newchannel->lock, flags); - /* The next possible work is rescind handling */ - INIT_WORK(&newchannel->work, vmbus_process_rescind_offer); - /* Check if rescind offer was already received */ - if (newchannel->rescind) - queue_work(newchannel->controlwq, &newchannel->work); - spin_unlock_irqrestore(&newchannel->lock, flags); + return; + err_free_chan: free_channel(newchannel); } @@ -526,8 +494,7 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) newchannel->monitor_grp = (u8)offer->monitorid / 32; newchannel->monitor_bit = (u8)offer->monitorid % 32; - INIT_WORK(&newchannel->work, vmbus_process_offer); - queue_work(newchannel->controlwq, &newchannel->work); + vmbus_process_offer(newchannel); } /* @@ -540,28 +507,30 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) struct vmbus_channel_rescind_offer *rescind; struct vmbus_channel *channel; unsigned long flags; + struct device *dev; rescind = (struct vmbus_channel_rescind_offer *)hdr; channel = relid2channel(rescind->child_relid); - if (channel == NULL) - /* Just return here, no channel found */ + if (channel == NULL) { + hv_process_channel_removal(NULL, rescind->child_relid); return; + } spin_lock_irqsave(&channel->lock, flags); channel->rescind = true; - /* - * channel->work.func != vmbus_process_rescind_offer means we are still - * processing offer request and the rescind offer processing should be - * postponed. It will be done at the very end of vmbus_process_offer() - * as rescind flag is being checked there. - */ - if (channel->work.func == vmbus_process_rescind_offer) - /* work is initialized for vmbus_process_rescind_offer() from - * vmbus_process_offer() where the channel got created */ - queue_work(channel->controlwq, &channel->work); - spin_unlock_irqrestore(&channel->lock, flags); + + if (channel->device_obj) { + dev = get_device(&channel->device_obj->device); + if (dev) { + vmbus_device_unregister(channel->device_obj); + put_device(dev); + } + } else { + hv_process_channel_removal(channel, + channel->offermsg.child_relid); + } } /* -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/