diff options
Diffstat (limited to 'drivers/hv')
-rw-r--r-- | drivers/hv/channel_mgmt.c | 75 | ||||
-rw-r--r-- | drivers/hv/hv_kvp.c | 24 | ||||
-rw-r--r-- | drivers/hv/hv_snapshot.c | 18 | ||||
-rw-r--r-- | drivers/hv/hv_util.c | 21 |
4 files changed, 100 insertions, 38 deletions
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 0df75908200e..12ec8c801b25 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c | |||
@@ -48,30 +48,39 @@ struct vmbus_channel_message_table_entry { | |||
48 | * @negop is of type &struct icmsg_negotiate. | 48 | * @negop is of type &struct icmsg_negotiate. |
49 | * Set up and fill in default negotiate response message. | 49 | * Set up and fill in default negotiate response message. |
50 | * | 50 | * |
51 | * The max_fw_version specifies the maximum framework version that | 51 | * The fw_version specifies the framework version that |
52 | * we can support and max _srv_version specifies the maximum service | 52 | * we can support and srv_version specifies the service |
53 | * version we can support. A special value MAX_SRV_VER can be | 53 | * version we can support. |
54 | * specified to indicate that we can handle the maximum version | ||
55 | * exposed by the host. | ||
56 | * | 54 | * |
57 | * Mainly used by Hyper-V drivers. | 55 | * Mainly used by Hyper-V drivers. |
58 | */ | 56 | */ |
59 | void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, | 57 | bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, |
60 | struct icmsg_negotiate *negop, u8 *buf, | 58 | struct icmsg_negotiate *negop, u8 *buf, |
61 | int max_fw_version, int max_srv_version) | 59 | int fw_version, int srv_version) |
62 | { | 60 | { |
63 | int icframe_vercnt; | 61 | int icframe_major, icframe_minor; |
64 | int icmsg_vercnt; | 62 | int icmsg_major, icmsg_minor; |
63 | int fw_major, fw_minor; | ||
64 | int srv_major, srv_minor; | ||
65 | int i; | 65 | int i; |
66 | bool found_match = false; | ||
66 | 67 | ||
67 | icmsghdrp->icmsgsize = 0x10; | 68 | icmsghdrp->icmsgsize = 0x10; |
69 | fw_major = (fw_version >> 16); | ||
70 | fw_minor = (fw_version & 0xFFFF); | ||
71 | |||
72 | srv_major = (srv_version >> 16); | ||
73 | srv_minor = (srv_version & 0xFFFF); | ||
68 | 74 | ||
69 | negop = (struct icmsg_negotiate *)&buf[ | 75 | negop = (struct icmsg_negotiate *)&buf[ |
70 | sizeof(struct vmbuspipe_hdr) + | 76 | sizeof(struct vmbuspipe_hdr) + |
71 | sizeof(struct icmsg_hdr)]; | 77 | sizeof(struct icmsg_hdr)]; |
72 | 78 | ||
73 | icframe_vercnt = negop->icframe_vercnt; | 79 | icframe_major = negop->icframe_vercnt; |
74 | icmsg_vercnt = negop->icmsg_vercnt; | 80 | icframe_minor = 0; |
81 | |||
82 | icmsg_major = negop->icmsg_vercnt; | ||
83 | icmsg_minor = 0; | ||
75 | 84 | ||
76 | /* | 85 | /* |
77 | * Select the framework version number we will | 86 | * Select the framework version number we will |
@@ -79,26 +88,48 @@ void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, | |||
79 | */ | 88 | */ |
80 | 89 | ||
81 | for (i = 0; i < negop->icframe_vercnt; i++) { | 90 | for (i = 0; i < negop->icframe_vercnt; i++) { |
82 | if (negop->icversion_data[i].major <= max_fw_version) | 91 | if ((negop->icversion_data[i].major == fw_major) && |
83 | icframe_vercnt = negop->icversion_data[i].major; | 92 | (negop->icversion_data[i].minor == fw_minor)) { |
93 | icframe_major = negop->icversion_data[i].major; | ||
94 | icframe_minor = negop->icversion_data[i].minor; | ||
95 | found_match = true; | ||
96 | } | ||
84 | } | 97 | } |
85 | 98 | ||
99 | if (!found_match) | ||
100 | goto fw_error; | ||
101 | |||
102 | found_match = false; | ||
103 | |||
86 | for (i = negop->icframe_vercnt; | 104 | for (i = negop->icframe_vercnt; |
87 | (i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) { | 105 | (i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) { |
88 | if (negop->icversion_data[i].major <= max_srv_version) | 106 | if ((negop->icversion_data[i].major == srv_major) && |
89 | icmsg_vercnt = negop->icversion_data[i].major; | 107 | (negop->icversion_data[i].minor == srv_minor)) { |
108 | icmsg_major = negop->icversion_data[i].major; | ||
109 | icmsg_minor = negop->icversion_data[i].minor; | ||
110 | found_match = true; | ||
111 | } | ||
90 | } | 112 | } |
91 | 113 | ||
92 | /* | 114 | /* |
93 | * Respond with the maximum framework and service | 115 | * Respond with the framework and service |
94 | * version numbers we can support. | 116 | * version numbers we can support. |
95 | */ | 117 | */ |
96 | negop->icframe_vercnt = 1; | 118 | |
97 | negop->icmsg_vercnt = 1; | 119 | fw_error: |
98 | negop->icversion_data[0].major = icframe_vercnt; | 120 | if (!found_match) { |
99 | negop->icversion_data[0].minor = 0; | 121 | negop->icframe_vercnt = 0; |
100 | negop->icversion_data[1].major = icmsg_vercnt; | 122 | negop->icmsg_vercnt = 0; |
101 | negop->icversion_data[1].minor = 0; | 123 | } else { |
124 | negop->icframe_vercnt = 1; | ||
125 | negop->icmsg_vercnt = 1; | ||
126 | } | ||
127 | |||
128 | negop->icversion_data[0].major = icframe_major; | ||
129 | negop->icversion_data[0].minor = icframe_minor; | ||
130 | negop->icversion_data[1].major = icmsg_major; | ||
131 | negop->icversion_data[1].minor = icmsg_minor; | ||
132 | return found_match; | ||
102 | } | 133 | } |
103 | 134 | ||
104 | EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); | 135 | EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); |
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index ed50e9e83c61..53127209a404 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c | |||
@@ -29,6 +29,16 @@ | |||
29 | #include <linux/hyperv.h> | 29 | #include <linux/hyperv.h> |
30 | 30 | ||
31 | 31 | ||
32 | /* | ||
33 | * Pre win8 version numbers used in ws2008 and ws 2008 r2 (win7) | ||
34 | */ | ||
35 | #define WIN7_SRV_MAJOR 3 | ||
36 | #define WIN7_SRV_MINOR 0 | ||
37 | #define WIN7_SRV_MAJOR_MINOR (WIN7_SRV_MAJOR << 16 | WIN7_SRV_MINOR) | ||
38 | |||
39 | #define WIN8_SRV_MAJOR 4 | ||
40 | #define WIN8_SRV_MINOR 0 | ||
41 | #define WIN8_SRV_MAJOR_MINOR (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR) | ||
32 | 42 | ||
33 | /* | 43 | /* |
34 | * Global state maintained for transaction that is being processed. | 44 | * Global state maintained for transaction that is being processed. |
@@ -593,8 +603,19 @@ void hv_kvp_onchannelcallback(void *context) | |||
593 | sizeof(struct vmbuspipe_hdr)]; | 603 | sizeof(struct vmbuspipe_hdr)]; |
594 | 604 | ||
595 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 605 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
606 | /* | ||
607 | * We start with win8 version and if the host cannot | ||
608 | * support that we use the previous version. | ||
609 | */ | ||
610 | if (vmbus_prep_negotiate_resp(icmsghdrp, negop, | ||
611 | recv_buffer, UTIL_FW_MAJOR_MINOR, | ||
612 | WIN8_SRV_MAJOR_MINOR)) | ||
613 | goto done; | ||
614 | |||
596 | vmbus_prep_negotiate_resp(icmsghdrp, negop, | 615 | vmbus_prep_negotiate_resp(icmsghdrp, negop, |
597 | recv_buffer, MAX_SRV_VER, MAX_SRV_VER); | 616 | recv_buffer, UTIL_FW_MAJOR_MINOR, |
617 | WIN7_SRV_MAJOR_MINOR); | ||
618 | |||
598 | } else { | 619 | } else { |
599 | kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ | 620 | kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ |
600 | sizeof(struct vmbuspipe_hdr) + | 621 | sizeof(struct vmbuspipe_hdr) + |
@@ -626,6 +647,7 @@ void hv_kvp_onchannelcallback(void *context) | |||
626 | return; | 647 | return; |
627 | 648 | ||
628 | } | 649 | } |
650 | done: | ||
629 | 651 | ||
630 | icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | 652 | icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION |
631 | | ICMSGHDRFLAG_RESPONSE; | 653 | | ICMSGHDRFLAG_RESPONSE; |
diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c index 8ad5653ce447..e4572f3f2834 100644 --- a/drivers/hv/hv_snapshot.c +++ b/drivers/hv/hv_snapshot.c | |||
@@ -24,6 +24,10 @@ | |||
24 | #include <linux/workqueue.h> | 24 | #include <linux/workqueue.h> |
25 | #include <linux/hyperv.h> | 25 | #include <linux/hyperv.h> |
26 | 26 | ||
27 | #define VSS_MAJOR 5 | ||
28 | #define VSS_MINOR 0 | ||
29 | #define VSS_MAJOR_MINOR (VSS_MAJOR << 16 | VSS_MINOR) | ||
30 | |||
27 | 31 | ||
28 | 32 | ||
29 | /* | 33 | /* |
@@ -186,18 +190,8 @@ void hv_vss_onchannelcallback(void *context) | |||
186 | 190 | ||
187 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 191 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
188 | vmbus_prep_negotiate_resp(icmsghdrp, negop, | 192 | vmbus_prep_negotiate_resp(icmsghdrp, negop, |
189 | recv_buffer, MAX_SRV_VER, MAX_SRV_VER); | 193 | recv_buffer, UTIL_FW_MAJOR_MINOR, |
190 | /* | 194 | VSS_MAJOR_MINOR); |
191 | * We currently negotiate the highest number the | ||
192 | * host has presented. If this version is not | ||
193 | * atleast 5.0, reject. | ||
194 | */ | ||
195 | negop = (struct icmsg_negotiate *)&recv_buffer[ | ||
196 | sizeof(struct vmbuspipe_hdr) + | ||
197 | sizeof(struct icmsg_hdr)]; | ||
198 | |||
199 | if (negop->icversion_data[1].major < 5) | ||
200 | negop->icframe_vercnt = 0; | ||
201 | } else { | 195 | } else { |
202 | vss_msg = (struct hv_vss_msg *)&recv_buffer[ | 196 | vss_msg = (struct hv_vss_msg *)&recv_buffer[ |
203 | sizeof(struct vmbuspipe_hdr) + | 197 | sizeof(struct vmbuspipe_hdr) + |
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c index 2f561c5dfe24..c16164d4a28b 100644 --- a/drivers/hv/hv_util.c +++ b/drivers/hv/hv_util.c | |||
@@ -28,6 +28,18 @@ | |||
28 | #include <linux/reboot.h> | 28 | #include <linux/reboot.h> |
29 | #include <linux/hyperv.h> | 29 | #include <linux/hyperv.h> |
30 | 30 | ||
31 | #define SHUTDOWN_MAJOR 3 | ||
32 | #define SHUTDOWN_MINOR 0 | ||
33 | #define SHUTDOWN_MAJOR_MINOR (SHUTDOWN_MAJOR << 16 | SHUTDOWN_MINOR) | ||
34 | |||
35 | #define TIMESYNCH_MAJOR 3 | ||
36 | #define TIMESYNCH_MINOR 0 | ||
37 | #define TIMESYNCH_MAJOR_MINOR (TIMESYNCH_MAJOR << 16 | TIMESYNCH_MINOR) | ||
38 | |||
39 | #define HEARTBEAT_MAJOR 3 | ||
40 | #define HEARTBEAT_MINOR 0 | ||
41 | #define HEARTBEAT_MAJOR_MINOR (HEARTBEAT_MAJOR << 16 | HEARTBEAT_MINOR) | ||
42 | |||
31 | static void shutdown_onchannelcallback(void *context); | 43 | static void shutdown_onchannelcallback(void *context); |
32 | static struct hv_util_service util_shutdown = { | 44 | static struct hv_util_service util_shutdown = { |
33 | .util_cb = shutdown_onchannelcallback, | 45 | .util_cb = shutdown_onchannelcallback, |
@@ -87,7 +99,8 @@ static void shutdown_onchannelcallback(void *context) | |||
87 | 99 | ||
88 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 100 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
89 | vmbus_prep_negotiate_resp(icmsghdrp, negop, | 101 | vmbus_prep_negotiate_resp(icmsghdrp, negop, |
90 | shut_txf_buf, MAX_SRV_VER, MAX_SRV_VER); | 102 | shut_txf_buf, UTIL_FW_MAJOR_MINOR, |
103 | SHUTDOWN_MAJOR_MINOR); | ||
91 | } else { | 104 | } else { |
92 | shutdown_msg = | 105 | shutdown_msg = |
93 | (struct shutdown_msg_data *)&shut_txf_buf[ | 106 | (struct shutdown_msg_data *)&shut_txf_buf[ |
@@ -213,7 +226,8 @@ static void timesync_onchannelcallback(void *context) | |||
213 | 226 | ||
214 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 227 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
215 | vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf, | 228 | vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf, |
216 | MAX_SRV_VER, MAX_SRV_VER); | 229 | UTIL_FW_MAJOR_MINOR, |
230 | TIMESYNCH_MAJOR_MINOR); | ||
217 | } else { | 231 | } else { |
218 | timedatap = (struct ictimesync_data *)&time_txf_buf[ | 232 | timedatap = (struct ictimesync_data *)&time_txf_buf[ |
219 | sizeof(struct vmbuspipe_hdr) + | 233 | sizeof(struct vmbuspipe_hdr) + |
@@ -253,7 +267,8 @@ static void heartbeat_onchannelcallback(void *context) | |||
253 | 267 | ||
254 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 268 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
255 | vmbus_prep_negotiate_resp(icmsghdrp, NULL, | 269 | vmbus_prep_negotiate_resp(icmsghdrp, NULL, |
256 | hbeat_txf_buf, MAX_SRV_VER, MAX_SRV_VER); | 270 | hbeat_txf_buf, UTIL_FW_MAJOR_MINOR, |
271 | HEARTBEAT_MAJOR_MINOR); | ||
257 | } else { | 272 | } else { |
258 | heartbeat_msg = | 273 | heartbeat_msg = |
259 | (struct heartbeat_msg_data *)&hbeat_txf_buf[ | 274 | (struct heartbeat_msg_data *)&hbeat_txf_buf[ |