aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hv
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hv')
-rw-r--r--drivers/hv/hv.c34
-rw-r--r--drivers/hv/hv_kvp.c253
-rw-r--r--drivers/hv/hv_util.c4
-rw-r--r--drivers/hv/hyperv_vmbus.h47
-rw-r--r--drivers/hv/vmbus_drv.c42
5 files changed, 283 insertions, 97 deletions
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 86f8885aeb45..3648f8f0f368 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -26,6 +26,7 @@
26#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/vmalloc.h> 27#include <linux/vmalloc.h>
28#include <linux/hyperv.h> 28#include <linux/hyperv.h>
29#include <linux/version.h>
29#include <asm/hyperv.h> 30#include <asm/hyperv.h>
30#include "hyperv_vmbus.h" 31#include "hyperv_vmbus.h"
31 32
@@ -38,28 +39,6 @@ struct hv_context hv_context = {
38}; 39};
39 40
40/* 41/*
41 * query_hypervisor_presence
42 * - Query the cpuid for presence of windows hypervisor
43 */
44static int query_hypervisor_presence(void)
45{
46 unsigned int eax;
47 unsigned int ebx;
48 unsigned int ecx;
49 unsigned int edx;
50 unsigned int op;
51
52 eax = 0;
53 ebx = 0;
54 ecx = 0;
55 edx = 0;
56 op = HVCPUID_VERSION_FEATURES;
57 cpuid(op, &eax, &ebx, &ecx, &edx);
58
59 return ecx & HV_PRESENT_BIT;
60}
61
62/*
63 * query_hypervisor_info - Get version info of the windows hypervisor 42 * query_hypervisor_info - Get version info of the windows hypervisor
64 */ 43 */
65static int query_hypervisor_info(void) 44static int query_hypervisor_info(void)
@@ -159,14 +138,13 @@ int hv_init(void)
159 memset(hv_context.synic_message_page, 0, 138 memset(hv_context.synic_message_page, 0,
160 sizeof(void *) * NR_CPUS); 139 sizeof(void *) * NR_CPUS);
161 140
162 if (!query_hypervisor_presence())
163 goto cleanup;
164
165 max_leaf = query_hypervisor_info(); 141 max_leaf = query_hypervisor_info();
166 142
167 /* Write our OS info */ 143 /*
168 wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID); 144 * Write our OS ID.
169 hv_context.guestid = HV_LINUX_GUEST_ID; 145 */
146 hv_context.guestid = generate_guest_id(0, LINUX_VERSION_CODE, 0);
147 wrmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid);
170 148
171 /* See if the hypercall page is already set */ 149 /* See if the hypercall page is already set */
172 rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); 150 rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 0012eed6d872..ed50e9e83c61 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -48,13 +48,24 @@ static struct {
48 void *kvp_context; /* for the channel callback */ 48 void *kvp_context; /* for the channel callback */
49} kvp_transaction; 49} kvp_transaction;
50 50
51/*
52 * Before we can accept KVP messages from the host, we need
53 * to handshake with the user level daemon. This state tracks
54 * if we are in the handshake phase.
55 */
56static bool in_hand_shake = true;
57
58/*
59 * This state maintains the version number registered by the daemon.
60 */
61static int dm_reg_value;
62
51static void kvp_send_key(struct work_struct *dummy); 63static void kvp_send_key(struct work_struct *dummy);
52 64
53#define TIMEOUT_FIRED 1
54 65
55static void kvp_respond_to_host(char *key, char *value, int error); 66static void kvp_respond_to_host(struct hv_kvp_msg *msg, int error);
56static void kvp_work_func(struct work_struct *dummy); 67static void kvp_work_func(struct work_struct *dummy);
57static void kvp_register(void); 68static void kvp_register(int);
58 69
59static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func); 70static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func);
60static DECLARE_WORK(kvp_sendkey_work, kvp_send_key); 71static DECLARE_WORK(kvp_sendkey_work, kvp_send_key);
@@ -68,7 +79,7 @@ static u8 *recv_buffer;
68 */ 79 */
69 80
70static void 81static void
71kvp_register(void) 82kvp_register(int reg_value)
72{ 83{
73 84
74 struct cn_msg *msg; 85 struct cn_msg *msg;
@@ -83,7 +94,7 @@ kvp_register(void)
83 msg->id.idx = CN_KVP_IDX; 94 msg->id.idx = CN_KVP_IDX;
84 msg->id.val = CN_KVP_VAL; 95 msg->id.val = CN_KVP_VAL;
85 96
86 kvp_msg->kvp_hdr.operation = KVP_OP_REGISTER; 97 kvp_msg->kvp_hdr.operation = reg_value;
87 strcpy(version, HV_DRV_VERSION); 98 strcpy(version, HV_DRV_VERSION);
88 msg->len = sizeof(struct hv_kvp_msg); 99 msg->len = sizeof(struct hv_kvp_msg);
89 cn_netlink_send(msg, 0, GFP_ATOMIC); 100 cn_netlink_send(msg, 0, GFP_ATOMIC);
@@ -97,9 +108,43 @@ kvp_work_func(struct work_struct *dummy)
97 * If the timer fires, the user-mode component has not responded; 108 * If the timer fires, the user-mode component has not responded;
98 * process the pending transaction. 109 * process the pending transaction.
99 */ 110 */
100 kvp_respond_to_host("Unknown key", "Guest timed out", TIMEOUT_FIRED); 111 kvp_respond_to_host(NULL, HV_E_FAIL);
112}
113
114static int kvp_handle_handshake(struct hv_kvp_msg *msg)
115{
116 int ret = 1;
117
118 switch (msg->kvp_hdr.operation) {
119 case KVP_OP_REGISTER:
120 dm_reg_value = KVP_OP_REGISTER;
121 pr_info("KVP: IP injection functionality not available\n");
122 pr_info("KVP: Upgrade the KVP daemon\n");
123 break;
124 case KVP_OP_REGISTER1:
125 dm_reg_value = KVP_OP_REGISTER1;
126 break;
127 default:
128 pr_info("KVP: incompatible daemon\n");
129 pr_info("KVP: KVP version: %d, Daemon version: %d\n",
130 KVP_OP_REGISTER1, msg->kvp_hdr.operation);
131 ret = 0;
132 }
133
134 if (ret) {
135 /*
136 * We have a compatible daemon; complete the handshake.
137 */
138 pr_info("KVP: user-mode registering done.\n");
139 kvp_register(dm_reg_value);
140 kvp_transaction.active = false;
141 if (kvp_transaction.kvp_context)
142 hv_kvp_onchannelcallback(kvp_transaction.kvp_context);
143 }
144 return ret;
101} 145}
102 146
147
103/* 148/*
104 * Callback when data is received from user mode. 149 * Callback when data is received from user mode.
105 */ 150 */
@@ -109,29 +154,165 @@ kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
109{ 154{
110 struct hv_kvp_msg *message; 155 struct hv_kvp_msg *message;
111 struct hv_kvp_msg_enumerate *data; 156 struct hv_kvp_msg_enumerate *data;
157 int error = 0;
112 158
113 message = (struct hv_kvp_msg *)msg->data; 159 message = (struct hv_kvp_msg *)msg->data;
114 switch (message->kvp_hdr.operation) { 160
161 /*
162 * If we are negotiating the version information
163 * with the daemon; handle that first.
164 */
165
166 if (in_hand_shake) {
167 if (kvp_handle_handshake(message))
168 in_hand_shake = false;
169 return;
170 }
171
172 /*
173 * Based on the version of the daemon, we propagate errors from the
174 * daemon differently.
175 */
176
177 data = &message->body.kvp_enum_data;
178
179 switch (dm_reg_value) {
115 case KVP_OP_REGISTER: 180 case KVP_OP_REGISTER:
116 pr_info("KVP: user-mode registering done.\n"); 181 /*
117 kvp_register(); 182 * Null string is used to pass back error condition.
118 kvp_transaction.active = false; 183 */
119 hv_kvp_onchannelcallback(kvp_transaction.kvp_context); 184 if (data->data.key[0] == 0)
185 error = HV_S_CONT;
120 break; 186 break;
121 187
122 default: 188 case KVP_OP_REGISTER1:
123 data = &message->body.kvp_enum_data;
124 /* 189 /*
125 * Complete the transaction by forwarding the key value 190 * We use the message header information from
126 * to the host. But first, cancel the timeout. 191 * the user level daemon to transmit errors.
127 */ 192 */
128 if (cancel_delayed_work_sync(&kvp_work)) 193 error = message->error;
129 kvp_respond_to_host(data->data.key, 194 break;
130 data->data.value, 195 }
131 !strlen(data->data.key)); 196
197 /*
198 * Complete the transaction by forwarding the key value
199 * to the host. But first, cancel the timeout.
200 */
201 if (cancel_delayed_work_sync(&kvp_work))
202 kvp_respond_to_host(message, error);
203}
204
205
206static int process_ob_ipinfo(void *in_msg, void *out_msg, int op)
207{
208 struct hv_kvp_msg *in = in_msg;
209 struct hv_kvp_ip_msg *out = out_msg;
210 int len;
211
212 switch (op) {
213 case KVP_OP_GET_IP_INFO:
214 /*
215 * Transform all parameters into utf16 encoding.
216 */
217 len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.ip_addr,
218 strlen((char *)in->body.kvp_ip_val.ip_addr),
219 UTF16_HOST_ENDIAN,
220 (wchar_t *)out->kvp_ip_val.ip_addr,
221 MAX_IP_ADDR_SIZE);
222 if (len < 0)
223 return len;
224
225 len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.sub_net,
226 strlen((char *)in->body.kvp_ip_val.sub_net),
227 UTF16_HOST_ENDIAN,
228 (wchar_t *)out->kvp_ip_val.sub_net,
229 MAX_IP_ADDR_SIZE);
230 if (len < 0)
231 return len;
232
233 len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.gate_way,
234 strlen((char *)in->body.kvp_ip_val.gate_way),
235 UTF16_HOST_ENDIAN,
236 (wchar_t *)out->kvp_ip_val.gate_way,
237 MAX_GATEWAY_SIZE);
238 if (len < 0)
239 return len;
240
241 len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.dns_addr,
242 strlen((char *)in->body.kvp_ip_val.dns_addr),
243 UTF16_HOST_ENDIAN,
244 (wchar_t *)out->kvp_ip_val.dns_addr,
245 MAX_IP_ADDR_SIZE);
246 if (len < 0)
247 return len;
248
249 len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.adapter_id,
250 strlen((char *)in->body.kvp_ip_val.adapter_id),
251 UTF16_HOST_ENDIAN,
252 (wchar_t *)out->kvp_ip_val.adapter_id,
253 MAX_IP_ADDR_SIZE);
254 if (len < 0)
255 return len;
256
257 out->kvp_ip_val.dhcp_enabled =
258 in->body.kvp_ip_val.dhcp_enabled;
259 out->kvp_ip_val.addr_family =
260 in->body.kvp_ip_val.addr_family;
261 }
262
263 return 0;
264}
265
266static void process_ib_ipinfo(void *in_msg, void *out_msg, int op)
267{
268 struct hv_kvp_ip_msg *in = in_msg;
269 struct hv_kvp_msg *out = out_msg;
270
271 switch (op) {
272 case KVP_OP_SET_IP_INFO:
273 /*
274 * Transform all parameters into utf8 encoding.
275 */
276 utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.ip_addr,
277 MAX_IP_ADDR_SIZE,
278 UTF16_LITTLE_ENDIAN,
279 (__u8 *)out->body.kvp_ip_val.ip_addr,
280 MAX_IP_ADDR_SIZE);
281
282 utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.sub_net,
283 MAX_IP_ADDR_SIZE,
284 UTF16_LITTLE_ENDIAN,
285 (__u8 *)out->body.kvp_ip_val.sub_net,
286 MAX_IP_ADDR_SIZE);
287
288 utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.gate_way,
289 MAX_GATEWAY_SIZE,
290 UTF16_LITTLE_ENDIAN,
291 (__u8 *)out->body.kvp_ip_val.gate_way,
292 MAX_GATEWAY_SIZE);
293
294 utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.dns_addr,
295 MAX_IP_ADDR_SIZE,
296 UTF16_LITTLE_ENDIAN,
297 (__u8 *)out->body.kvp_ip_val.dns_addr,
298 MAX_IP_ADDR_SIZE);
299
300 out->body.kvp_ip_val.dhcp_enabled = in->kvp_ip_val.dhcp_enabled;
301
302 default:
303 utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.adapter_id,
304 MAX_ADAPTER_ID_SIZE,
305 UTF16_LITTLE_ENDIAN,
306 (__u8 *)out->body.kvp_ip_val.adapter_id,
307 MAX_ADAPTER_ID_SIZE);
308
309 out->body.kvp_ip_val.addr_family = in->kvp_ip_val.addr_family;
132 } 310 }
133} 311}
134 312
313
314
315
135static void 316static void
136kvp_send_key(struct work_struct *dummy) 317kvp_send_key(struct work_struct *dummy)
137{ 318{
@@ -167,6 +348,12 @@ kvp_send_key(struct work_struct *dummy)
167 */ 348 */
168 349
169 switch (message->kvp_hdr.operation) { 350 switch (message->kvp_hdr.operation) {
351 case KVP_OP_SET_IP_INFO:
352 process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO);
353 break;
354 case KVP_OP_GET_IP_INFO:
355 process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO);
356 break;
170 case KVP_OP_SET: 357 case KVP_OP_SET:
171 switch (in_msg->body.kvp_set.data.value_type) { 358 switch (in_msg->body.kvp_set.data.value_type) {
172 case REG_SZ: 359 case REG_SZ:
@@ -243,17 +430,19 @@ kvp_send_key(struct work_struct *dummy)
243 */ 430 */
244 431
245static void 432static void
246kvp_respond_to_host(char *key, char *value, int error) 433kvp_respond_to_host(struct hv_kvp_msg *msg_to_host, int error)
247{ 434{
248 struct hv_kvp_msg *kvp_msg; 435 struct hv_kvp_msg *kvp_msg;
249 struct hv_kvp_exchg_msg_value *kvp_data; 436 struct hv_kvp_exchg_msg_value *kvp_data;
250 char *key_name; 437 char *key_name;
438 char *value;
251 struct icmsg_hdr *icmsghdrp; 439 struct icmsg_hdr *icmsghdrp;
252 int keylen = 0; 440 int keylen = 0;
253 int valuelen = 0; 441 int valuelen = 0;
254 u32 buf_len; 442 u32 buf_len;
255 struct vmbus_channel *channel; 443 struct vmbus_channel *channel;
256 u64 req_id; 444 u64 req_id;
445 int ret;
257 446
258 /* 447 /*
259 * If a transaction is not active; log and return. 448 * If a transaction is not active; log and return.
@@ -287,6 +476,7 @@ kvp_respond_to_host(char *key, char *value, int error)
287 */ 476 */
288 return; 477 return;
289 478
479 icmsghdrp->status = error;
290 480
291 /* 481 /*
292 * If the error parameter is set, terminate the host's enumeration 482 * If the error parameter is set, terminate the host's enumeration
@@ -294,20 +484,27 @@ kvp_respond_to_host(char *key, char *value, int error)
294 */ 484 */
295 if (error) { 485 if (error) {
296 /* 486 /*
297 * Something failed or the we have timedout; 487 * Something failed or we have timedout;
298 * terminate the current host-side iteration. 488 * terminate the current host-side iteration.
299 */ 489 */
300 icmsghdrp->status = HV_S_CONT;
301 goto response_done; 490 goto response_done;
302 } 491 }
303 492
304 icmsghdrp->status = HV_S_OK;
305
306 kvp_msg = (struct hv_kvp_msg *) 493 kvp_msg = (struct hv_kvp_msg *)
307 &recv_buffer[sizeof(struct vmbuspipe_hdr) + 494 &recv_buffer[sizeof(struct vmbuspipe_hdr) +
308 sizeof(struct icmsg_hdr)]; 495 sizeof(struct icmsg_hdr)];
309 496
310 switch (kvp_transaction.kvp_msg->kvp_hdr.operation) { 497 switch (kvp_transaction.kvp_msg->kvp_hdr.operation) {
498 case KVP_OP_GET_IP_INFO:
499 ret = process_ob_ipinfo(msg_to_host,
500 (struct hv_kvp_ip_msg *)kvp_msg,
501 KVP_OP_GET_IP_INFO);
502 if (ret < 0)
503 icmsghdrp->status = HV_E_FAIL;
504
505 goto response_done;
506 case KVP_OP_SET_IP_INFO:
507 goto response_done;
311 case KVP_OP_GET: 508 case KVP_OP_GET:
312 kvp_data = &kvp_msg->body.kvp_get.data; 509 kvp_data = &kvp_msg->body.kvp_get.data;
313 goto copy_value; 510 goto copy_value;
@@ -321,7 +518,7 @@ kvp_respond_to_host(char *key, char *value, int error)
321 } 518 }
322 519
323 kvp_data = &kvp_msg->body.kvp_enum_data.data; 520 kvp_data = &kvp_msg->body.kvp_enum_data.data;
324 key_name = key; 521 key_name = msg_to_host->body.kvp_enum_data.data.key;
325 522
326 /* 523 /*
327 * The windows host expects the key/value pair to be encoded 524 * The windows host expects the key/value pair to be encoded
@@ -335,6 +532,7 @@ kvp_respond_to_host(char *key, char *value, int error)
335 kvp_data->key_size = 2*(keylen + 1); /* utf16 encoding */ 532 kvp_data->key_size = 2*(keylen + 1); /* utf16 encoding */
336 533
337copy_value: 534copy_value:
535 value = msg_to_host->body.kvp_enum_data.data.value;
338 valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN, 536 valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN,
339 (wchar_t *) kvp_data->value, 537 (wchar_t *) kvp_data->value,
340 (HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2); 538 (HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2);
@@ -387,7 +585,8 @@ void hv_kvp_onchannelcallback(void *context)
387 return; 585 return;
388 } 586 }
389 587
390 vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid); 588 vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen,
589 &requestid);
391 590
392 if (recvlen > 0) { 591 if (recvlen > 0) {
393 icmsghdrp = (struct icmsg_hdr *)&recv_buffer[ 592 icmsghdrp = (struct icmsg_hdr *)&recv_buffer[
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index d3ac6a40118b..a0667de7a04c 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -263,7 +263,7 @@ static int util_probe(struct hv_device *dev,
263 (struct hv_util_service *)dev_id->driver_data; 263 (struct hv_util_service *)dev_id->driver_data;
264 int ret; 264 int ret;
265 265
266 srv->recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); 266 srv->recv_buffer = kmalloc(PAGE_SIZE * 2, GFP_KERNEL);
267 if (!srv->recv_buffer) 267 if (!srv->recv_buffer)
268 return -ENOMEM; 268 return -ENOMEM;
269 if (srv->util_init) { 269 if (srv->util_init) {
@@ -274,7 +274,7 @@ static int util_probe(struct hv_device *dev,
274 } 274 }
275 } 275 }
276 276
277 ret = vmbus_open(dev->channel, 2 * PAGE_SIZE, 2 * PAGE_SIZE, NULL, 0, 277 ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0,
278 srv->util_cb, dev->channel); 278 srv->util_cb, dev->channel);
279 if (ret) 279 if (ret)
280 goto error; 280 goto error;
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 0614ff3a7d7e..d8d1fadb398a 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -410,10 +410,49 @@ enum {
410 410
411#define HV_PRESENT_BIT 0x80000000 411#define HV_PRESENT_BIT 0x80000000
412 412
413#define HV_LINUX_GUEST_ID_LO 0x00000000 413/*
414#define HV_LINUX_GUEST_ID_HI 2976579765 414 * The guest OS needs to register the guest ID with the hypervisor.
415#define HV_LINUX_GUEST_ID (((u64)HV_LINUX_GUEST_ID_HI << 32) | \ 415 * The guest ID is a 64 bit entity and the structure of this ID is
416 HV_LINUX_GUEST_ID_LO) 416 * specified in the Hyper-V specification:
417 *
418 * http://msdn.microsoft.com/en-us/library/windows/hardware/ff542653%28v=vs.85%29.aspx
419 *
420 * While the current guideline does not specify how Linux guest ID(s)
421 * need to be generated, our plan is to publish the guidelines for
422 * Linux and other guest operating systems that currently are hosted
423 * on Hyper-V. The implementation here conforms to this yet
424 * unpublished guidelines.
425 *
426 *
427 * Bit(s)
428 * 63 - Indicates if the OS is Open Source or not; 1 is Open Source
429 * 62:56 - Os Type; Linux is 0x100
430 * 55:48 - Distro specific identification
431 * 47:16 - Linux kernel version number
432 * 15:0 - Distro specific identification
433 *
434 *
435 */
436
437#define HV_LINUX_VENDOR_ID 0x8100
438
439/*
440 * Generate the guest ID based on the guideline described above.
441 */
442
443static inline __u64 generate_guest_id(__u8 d_info1, __u32 kernel_version,
444 __u16 d_info2)
445{
446 __u64 guest_id = 0;
447
448 guest_id = (((__u64)HV_LINUX_VENDOR_ID) << 48);
449 guest_id |= (((__u64)(d_info1)) << 48);
450 guest_id |= (((__u64)(kernel_version)) << 16);
451 guest_id |= ((__u64)(d_info2));
452
453 return guest_id;
454}
455
417 456
418#define HV_CPU_POWER_MANAGEMENT (1 << 0) 457#define HV_CPU_POWER_MANAGEMENT (1 << 0)
419#define HV_RECOMMENDATIONS_MAX 4 458#define HV_RECOMMENDATIONS_MAX 4
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 4748086eaaf2..8e1a9ec53003 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -34,6 +34,7 @@
34#include <linux/completion.h> 34#include <linux/completion.h>
35#include <linux/hyperv.h> 35#include <linux/hyperv.h>
36#include <asm/hyperv.h> 36#include <asm/hyperv.h>
37#include <asm/hypervisor.h>
37#include "hyperv_vmbus.h" 38#include "hyperv_vmbus.h"
38 39
39 40
@@ -146,43 +147,9 @@ static ssize_t vmbus_show_device_attr(struct device *dev,
146 get_channel_info(hv_dev, device_info); 147 get_channel_info(hv_dev, device_info);
147 148
148 if (!strcmp(dev_attr->attr.name, "class_id")) { 149 if (!strcmp(dev_attr->attr.name, "class_id")) {
149 ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-" 150 ret = sprintf(buf, "{%pUl}\n", device_info->chn_type.b);
150 "%02x%02x%02x%02x%02x%02x%02x%02x}\n",
151 device_info->chn_type.b[3],
152 device_info->chn_type.b[2],
153 device_info->chn_type.b[1],
154 device_info->chn_type.b[0],
155 device_info->chn_type.b[5],
156 device_info->chn_type.b[4],
157 device_info->chn_type.b[7],
158 device_info->chn_type.b[6],
159 device_info->chn_type.b[8],
160 device_info->chn_type.b[9],
161 device_info->chn_type.b[10],
162 device_info->chn_type.b[11],
163 device_info->chn_type.b[12],
164 device_info->chn_type.b[13],
165 device_info->chn_type.b[14],
166 device_info->chn_type.b[15]);
167 } else if (!strcmp(dev_attr->attr.name, "device_id")) { 151 } else if (!strcmp(dev_attr->attr.name, "device_id")) {
168 ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-" 152 ret = sprintf(buf, "{%pUl}\n", device_info->chn_instance.b);
169 "%02x%02x%02x%02x%02x%02x%02x%02x}\n",
170 device_info->chn_instance.b[3],
171 device_info->chn_instance.b[2],
172 device_info->chn_instance.b[1],
173 device_info->chn_instance.b[0],
174 device_info->chn_instance.b[5],
175 device_info->chn_instance.b[4],
176 device_info->chn_instance.b[7],
177 device_info->chn_instance.b[6],
178 device_info->chn_instance.b[8],
179 device_info->chn_instance.b[9],
180 device_info->chn_instance.b[10],
181 device_info->chn_instance.b[11],
182 device_info->chn_instance.b[12],
183 device_info->chn_instance.b[13],
184 device_info->chn_instance.b[14],
185 device_info->chn_instance.b[15]);
186 } else if (!strcmp(dev_attr->attr.name, "modalias")) { 153 } else if (!strcmp(dev_attr->attr.name, "modalias")) {
187 print_alias_name(hv_dev, alias_name); 154 print_alias_name(hv_dev, alias_name);
188 ret = sprintf(buf, "vmbus:%s\n", alias_name); 155 ret = sprintf(buf, "vmbus:%s\n", alias_name);
@@ -757,6 +724,9 @@ static int __init hv_acpi_init(void)
757{ 724{
758 int ret, t; 725 int ret, t;
759 726
727 if (x86_hyper != &x86_hyper_ms_hyperv)
728 return -ENODEV;
729
760 init_completion(&probe_event); 730 init_completion(&probe_event);
761 731
762 /* 732 /*