aboutsummaryrefslogtreecommitdiff
path: root/drivers/hv/channel_mgmt.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-03 11:36:27 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-03 11:36:27 -0700
commit1d1fdd95df681f0c065d90ffaafa215a0e8825e2 (patch)
tree19016e131bb5c7eb280a4cc8dff864ba36e53be4 /drivers/hv/channel_mgmt.c
parentb3b49114c80e799af8b08c0c6d1ff886ea843f03 (diff)
parent3cc1f95283a125cf54ccf1e25065321d4385133b (diff)
Merge tag 'char-misc-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc patches from Greg KH: "Here is the big char/misc driver pull request for 3.12-rc1 Lots of driver updates all over the char/misc tree, full details in the shortlog" * tag 'char-misc-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (62 commits) drivers: uio: Kconfig: add MMU dependancy for UIO drivers: uio: Add driver for Humusoft MF624 DAQ PCI card drivers: uio_pdrv_genirq: use dev_get_platdata() drivers: uio_pruss: use dev_get_platdata() drivers: uio_dmem_genirq: use dev_get_platdata() drivers: parport: Kconfig: exclude h8300 for PARPORT_PC drivers: misc: ti-st: fix potential race if st_kim_start fails Drivers: hv: vmbus: Do not attempt to negoatiate a new version prematurely misc: vmw_balloon: Remove braces to fix build for clang. Drivers: hv: vmbus: Fix a bug in the handling of channel offers vme: vme_ca91cx42.c: fix to pass correct device identity to free_irq() VMCI: Add support for virtual IOMMU VMCI: Remove non-blocking/pinned queuepair support uio: uio_pruss: remove unnecessary platform_set_drvdata() parport: amiga: remove unnecessary platform_set_drvdata() vme: vme_vmivme7805.c: add missing __iomem annotation vme: vme_ca91cx42.c: add missing __iomem annotation vme: vme_tsi148.c: add missing __iomem annotation drivers/misc/hpilo: Correct panic when an AUX iLO is detected uio: drop unused vma_count member in uio_device struct ...
Diffstat (limited to 'drivers/hv/channel_mgmt.c')
-rw-r--r--drivers/hv/channel_mgmt.c89
1 files changed, 60 insertions, 29 deletions
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 0df75908200..bbff5f200be 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -48,30 +48,39 @@ struct vmbus_channel_message_table_entry {
* @negop is of type &struct icmsg_negotiate.
* Set up and fill in default negotiate response message.
*
- * The max_fw_version specifies the maximum framework version that
- * we can support and max _srv_version specifies the maximum service
- * version we can support. A special value MAX_SRV_VER can be
- * specified to indicate that we can handle the maximum version
- * exposed by the host.
+ * The fw_version specifies the framework version that
+ * we can support and srv_version specifies the service
+ * version we can support.
*
* Mainly used by Hyper-V drivers.
*/
-void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
+bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
struct icmsg_negotiate *negop, u8 *buf,
- int max_fw_version, int max_srv_version)
+ int fw_version, int srv_version)
{
- int icframe_vercnt;
- int icmsg_vercnt;
+ int icframe_major, icframe_minor;
+ int icmsg_major, icmsg_minor;
+ int fw_major, fw_minor;
+ int srv_major, srv_minor;
int i;
+ bool found_match = false;
icmsghdrp->icmsgsize = 0x10;
+ fw_major = (fw_version >> 16);
+ fw_minor = (fw_version & 0xFFFF);
+
+ srv_major = (srv_version >> 16);
+ srv_minor = (srv_version & 0xFFFF);
negop = (struct icmsg_negotiate *)&buf[
sizeof(struct vmbuspipe_hdr) +
sizeof(struct icmsg_hdr)];
- icframe_vercnt = negop->icframe_vercnt;
- icmsg_vercnt = negop->icmsg_vercnt;
+ icframe_major = negop->icframe_vercnt;
+ icframe_minor = 0;
+
+ icmsg_major = negop->icmsg_vercnt;
+ icmsg_minor = 0;
/*
* Select the framework version number we will
@@ -79,26 +88,48 @@ void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
*/
for (i = 0; i < negop->icframe_vercnt; i++) {
- if (negop->icversion_data[i].major <= max_fw_version)
- icframe_vercnt = negop->icversion_data[i].major;
+ if ((negop->icversion_data[i].major == fw_major) &&
+ (negop->icversion_data[i].minor == fw_minor)) {
+ icframe_major = negop->icversion_data[i].major;
+ icframe_minor = negop->icversion_data[i].minor;
+ found_match = true;
+ }
}
+ if (!found_match)
+ goto fw_error;
+
+ found_match = false;
+
for (i = negop->icframe_vercnt;
(i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) {
- if (negop->icversion_data[i].major <= max_srv_version)
- icmsg_vercnt = negop->icversion_data[i].major;
+ if ((negop->icversion_data[i].major == srv_major) &&
+ (negop->icversion_data[i].minor == srv_minor)) {
+ icmsg_major = negop->icversion_data[i].major;
+ icmsg_minor = negop->icversion_data[i].minor;
+ found_match = true;
+ }
}
/*
- * Respond with the maximum framework and service
+ * Respond with the framework and service
* version numbers we can support.
*/
- negop->icframe_vercnt = 1;
- negop->icmsg_vercnt = 1;
- negop->icversion_data[0].major = icframe_vercnt;
- negop->icversion_data[0].minor = 0;
- negop->icversion_data[1].major = icmsg_vercnt;
- negop->icversion_data[1].minor = 0;
+
+fw_error:
+ if (!found_match) {
+ negop->icframe_vercnt = 0;
+ negop->icmsg_vercnt = 0;
+ } else {
+ negop->icframe_vercnt = 1;
+ negop->icmsg_vercnt = 1;
+ }
+
+ negop->icversion_data[0].major = icframe_major;
+ negop->icversion_data[0].minor = icframe_minor;
+ negop->icversion_data[1].major = icmsg_major;
+ negop->icversion_data[1].minor = icmsg_minor;
+ return found_match;
}
EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp);
@@ -262,6 +293,13 @@ static void vmbus_process_offer(struct work_struct *work)
}
/*
+ * This state is used to indicate a successful open
+ * so that when we do close the channel normally, we
+ * can cleanup properly
+ */
+ newchannel->state = CHANNEL_OPEN_STATE;
+
+ /*
* Start the process of binding this offer to the driver
* We need to set the DeviceObject field before calling
* vmbus_child_dev_add()
@@ -287,13 +325,6 @@ static void vmbus_process_offer(struct work_struct *work)
kfree(newchannel->device_obj);
free_channel(newchannel);
- } else {
- /*
- * This state is used to indicate a successful open
- * so that when we do close the channel normally, we
- * can cleanup properly
- */
- newchannel->state = CHANNEL_OPEN_STATE;
}
}