diff options
| -rw-r--r-- | drivers/staging/hv/Hv.c | 50 | ||||
| -rw-r--r-- | drivers/staging/hv/Hv.h | 6 | ||||
| -rw-r--r-- | drivers/staging/hv/Vmbus.c | 12 |
3 files changed, 35 insertions, 33 deletions
diff --git a/drivers/staging/hv/Hv.c b/drivers/staging/hv/Hv.c index c5b6613f2f2f..c2809f2a2ce0 100644 --- a/drivers/staging/hv/Hv.c +++ b/drivers/staging/hv/Hv.c | |||
| @@ -386,7 +386,7 @@ u16 HvSignalEvent(void) | |||
| 386 | * retrieve the initialized message and event pages. Otherwise, we create and | 386 | * retrieve the initialized message and event pages. Otherwise, we create and |
| 387 | * initialize the message and event pages. | 387 | * initialize the message and event pages. |
| 388 | */ | 388 | */ |
| 389 | int HvSynicInit(u32 irqVector) | 389 | void HvSynicInit(void *irqarg) |
| 390 | { | 390 | { |
| 391 | u64 version; | 391 | u64 version; |
| 392 | union hv_synic_simp simp; | 392 | union hv_synic_simp simp; |
| @@ -394,13 +394,14 @@ int HvSynicInit(u32 irqVector) | |||
| 394 | union hv_synic_sint sharedSint; | 394 | union hv_synic_sint sharedSint; |
| 395 | union hv_synic_scontrol sctrl; | 395 | union hv_synic_scontrol sctrl; |
| 396 | u64 guestID; | 396 | u64 guestID; |
| 397 | int ret = 0; | 397 | u32 irqVector = *((u32 *)(irqarg)); |
| 398 | int cpu = smp_processor_id(); | ||
| 398 | 399 | ||
| 399 | DPRINT_ENTER(VMBUS); | 400 | DPRINT_ENTER(VMBUS); |
| 400 | 401 | ||
| 401 | if (!gHvContext.HypercallPage) { | 402 | if (!gHvContext.HypercallPage) { |
| 402 | DPRINT_EXIT(VMBUS); | 403 | DPRINT_EXIT(VMBUS); |
| 403 | return ret; | 404 | return; |
| 404 | } | 405 | } |
| 405 | 406 | ||
| 406 | /* Check the version */ | 407 | /* Check the version */ |
| @@ -425,27 +426,27 @@ int HvSynicInit(u32 irqVector) | |||
| 425 | */ | 426 | */ |
| 426 | rdmsrl(HV_X64_MSR_GUEST_OS_ID, guestID); | 427 | rdmsrl(HV_X64_MSR_GUEST_OS_ID, guestID); |
| 427 | if (guestID == HV_LINUX_GUEST_ID) { | 428 | if (guestID == HV_LINUX_GUEST_ID) { |
| 428 | gHvContext.synICMessagePage[0] = | 429 | gHvContext.synICMessagePage[cpu] = |
| 429 | phys_to_virt(simp.BaseSimpGpa << PAGE_SHIFT); | 430 | phys_to_virt(simp.BaseSimpGpa << PAGE_SHIFT); |
| 430 | gHvContext.synICEventPage[0] = | 431 | gHvContext.synICEventPage[cpu] = |
| 431 | phys_to_virt(siefp.BaseSiefpGpa << PAGE_SHIFT); | 432 | phys_to_virt(siefp.BaseSiefpGpa << PAGE_SHIFT); |
| 432 | } else { | 433 | } else { |
| 433 | DPRINT_ERR(VMBUS, "unknown guest id!!"); | 434 | DPRINT_ERR(VMBUS, "unknown guest id!!"); |
| 434 | goto Cleanup; | 435 | goto Cleanup; |
| 435 | } | 436 | } |
| 436 | DPRINT_DBG(VMBUS, "MAPPED: Simp: %p, Sifep: %p", | 437 | DPRINT_DBG(VMBUS, "MAPPED: Simp: %p, Sifep: %p", |
| 437 | gHvContext.synICMessagePage[0], | 438 | gHvContext.synICMessagePage[cpu], |
| 438 | gHvContext.synICEventPage[0]); | 439 | gHvContext.synICEventPage[cpu]); |
| 439 | } else { | 440 | } else { |
| 440 | gHvContext.synICMessagePage[0] = osd_PageAlloc(1); | 441 | gHvContext.synICMessagePage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC); |
| 441 | if (gHvContext.synICMessagePage[0] == NULL) { | 442 | if (gHvContext.synICMessagePage[cpu] == NULL) { |
| 442 | DPRINT_ERR(VMBUS, | 443 | DPRINT_ERR(VMBUS, |
| 443 | "unable to allocate SYNIC message page!!"); | 444 | "unable to allocate SYNIC message page!!"); |
| 444 | goto Cleanup; | 445 | goto Cleanup; |
| 445 | } | 446 | } |
| 446 | 447 | ||
| 447 | gHvContext.synICEventPage[0] = osd_PageAlloc(1); | 448 | gHvContext.synICEventPage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC); |
| 448 | if (gHvContext.synICEventPage[0] == NULL) { | 449 | if (gHvContext.synICEventPage[cpu] == NULL) { |
| 449 | DPRINT_ERR(VMBUS, | 450 | DPRINT_ERR(VMBUS, |
| 450 | "unable to allocate SYNIC event page!!"); | 451 | "unable to allocate SYNIC event page!!"); |
| 451 | goto Cleanup; | 452 | goto Cleanup; |
| @@ -454,7 +455,7 @@ int HvSynicInit(u32 irqVector) | |||
| 454 | /* Setup the Synic's message page */ | 455 | /* Setup the Synic's message page */ |
| 455 | rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64); | 456 | rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64); |
| 456 | simp.SimpEnabled = 1; | 457 | simp.SimpEnabled = 1; |
| 457 | simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[0]) | 458 | simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[cpu]) |
| 458 | >> PAGE_SHIFT; | 459 | >> PAGE_SHIFT; |
| 459 | 460 | ||
| 460 | DPRINT_DBG(VMBUS, "HV_X64_MSR_SIMP msr set to: %llx", | 461 | DPRINT_DBG(VMBUS, "HV_X64_MSR_SIMP msr set to: %llx", |
| @@ -465,7 +466,7 @@ int HvSynicInit(u32 irqVector) | |||
| 465 | /* Setup the Synic's event page */ | 466 | /* Setup the Synic's event page */ |
| 466 | rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64); | 467 | rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64); |
| 467 | siefp.SiefpEnabled = 1; | 468 | siefp.SiefpEnabled = 1; |
| 468 | siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[0]) | 469 | siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[cpu]) |
| 469 | >> PAGE_SHIFT; | 470 | >> PAGE_SHIFT; |
| 470 | 471 | ||
| 471 | DPRINT_DBG(VMBUS, "HV_X64_MSR_SIEFP msr set to: %llx", | 472 | DPRINT_DBG(VMBUS, "HV_X64_MSR_SIEFP msr set to: %llx", |
| @@ -501,32 +502,30 @@ int HvSynicInit(u32 irqVector) | |||
| 501 | 502 | ||
| 502 | DPRINT_EXIT(VMBUS); | 503 | DPRINT_EXIT(VMBUS); |
| 503 | 504 | ||
| 504 | return ret; | 505 | return; |
| 505 | 506 | ||
| 506 | Cleanup: | 507 | Cleanup: |
| 507 | ret = -1; | ||
| 508 | |||
| 509 | if (gHvContext.GuestId == HV_LINUX_GUEST_ID) { | 508 | if (gHvContext.GuestId == HV_LINUX_GUEST_ID) { |
| 510 | if (gHvContext.synICEventPage[0]) | 509 | if (gHvContext.synICEventPage[cpu]) |
| 511 | osd_PageFree(gHvContext.synICEventPage[0], 1); | 510 | osd_PageFree(gHvContext.synICEventPage[cpu], 1); |
| 512 | 511 | ||
| 513 | if (gHvContext.synICMessagePage[0]) | 512 | if (gHvContext.synICMessagePage[cpu]) |
| 514 | osd_PageFree(gHvContext.synICMessagePage[0], 1); | 513 | osd_PageFree(gHvContext.synICMessagePage[cpu], 1); |
| 515 | } | 514 | } |
| 516 | 515 | ||
| 517 | DPRINT_EXIT(VMBUS); | 516 | DPRINT_EXIT(VMBUS); |
| 518 | 517 | return; | |
| 519 | return ret; | ||
| 520 | } | 518 | } |
| 521 | 519 | ||
| 522 | /** | 520 | /** |
| 523 | * HvSynicCleanup - Cleanup routine for HvSynicInit(). | 521 | * HvSynicCleanup - Cleanup routine for HvSynicInit(). |
| 524 | */ | 522 | */ |
| 525 | void HvSynicCleanup(void) | 523 | void HvSynicCleanup(void *arg) |
| 526 | { | 524 | { |
| 527 | union hv_synic_sint sharedSint; | 525 | union hv_synic_sint sharedSint; |
| 528 | union hv_synic_simp simp; | 526 | union hv_synic_simp simp; |
| 529 | union hv_synic_siefp siefp; | 527 | union hv_synic_siefp siefp; |
| 528 | int cpu = smp_processor_id(); | ||
| 530 | 529 | ||
| 531 | DPRINT_ENTER(VMBUS); | 530 | DPRINT_ENTER(VMBUS); |
| 532 | 531 | ||
| @@ -539,6 +538,7 @@ void HvSynicCleanup(void) | |||
| 539 | 538 | ||
| 540 | sharedSint.Masked = 1; | 539 | sharedSint.Masked = 1; |
| 541 | 540 | ||
| 541 | /* Need to correctly cleanup in the case of SMP!!! */ | ||
| 542 | /* Disable the interrupt */ | 542 | /* Disable the interrupt */ |
| 543 | wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64); | 543 | wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64); |
| 544 | 544 | ||
| @@ -560,8 +560,8 @@ void HvSynicCleanup(void) | |||
| 560 | 560 | ||
| 561 | wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64); | 561 | wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64); |
| 562 | 562 | ||
| 563 | osd_PageFree(gHvContext.synICMessagePage[0], 1); | 563 | osd_PageFree(gHvContext.synICMessagePage[cpu], 1); |
| 564 | osd_PageFree(gHvContext.synICEventPage[0], 1); | 564 | osd_PageFree(gHvContext.synICEventPage[cpu], 1); |
| 565 | } | 565 | } |
| 566 | 566 | ||
| 567 | DPRINT_EXIT(VMBUS); | 567 | DPRINT_EXIT(VMBUS); |
diff --git a/drivers/staging/hv/Hv.h b/drivers/staging/hv/Hv.h index 5379e4bfc56e..fce4b5cdac30 100644 --- a/drivers/staging/hv/Hv.h +++ b/drivers/staging/hv/Hv.h | |||
| @@ -93,7 +93,7 @@ static const struct hv_guid VMBUS_SERVICE_ID = { | |||
| 93 | }, | 93 | }, |
| 94 | }; | 94 | }; |
| 95 | 95 | ||
| 96 | #define MAX_NUM_CPUS 1 | 96 | #define MAX_NUM_CPUS 32 |
| 97 | 97 | ||
| 98 | 98 | ||
| 99 | struct hv_input_signal_event_buffer { | 99 | struct hv_input_signal_event_buffer { |
| @@ -137,8 +137,8 @@ extern u16 HvPostMessage(union hv_connection_id connectionId, | |||
| 137 | 137 | ||
| 138 | extern u16 HvSignalEvent(void); | 138 | extern u16 HvSignalEvent(void); |
| 139 | 139 | ||
| 140 | extern int HvSynicInit(u32 irqVector); | 140 | extern void HvSynicInit(void *irqarg); |
| 141 | 141 | ||
| 142 | extern void HvSynicCleanup(void); | 142 | extern void HvSynicCleanup(void *arg); |
| 143 | 143 | ||
| 144 | #endif /* __HV_H__ */ | 144 | #endif /* __HV_H__ */ |
diff --git a/drivers/staging/hv/Vmbus.c b/drivers/staging/hv/Vmbus.c index a4dd06f6d459..35a023e9f9d1 100644 --- a/drivers/staging/hv/Vmbus.c +++ b/drivers/staging/hv/Vmbus.c | |||
| @@ -129,7 +129,7 @@ static int VmbusOnDeviceAdd(struct hv_device *dev, void *AdditionalInfo) | |||
| 129 | 129 | ||
| 130 | /* strcpy(dev->name, "vmbus"); */ | 130 | /* strcpy(dev->name, "vmbus"); */ |
| 131 | /* SynIC setup... */ | 131 | /* SynIC setup... */ |
| 132 | ret = HvSynicInit(*irqvector); | 132 | on_each_cpu(HvSynicInit, (void *)irqvector, 1); |
| 133 | 133 | ||
| 134 | /* Connect to VMBus in the root partition */ | 134 | /* Connect to VMBus in the root partition */ |
| 135 | ret = VmbusConnect(); | 135 | ret = VmbusConnect(); |
| @@ -150,7 +150,7 @@ static int VmbusOnDeviceRemove(struct hv_device *dev) | |||
| 150 | DPRINT_ENTER(VMBUS); | 150 | DPRINT_ENTER(VMBUS); |
| 151 | VmbusChannelReleaseUnattachedChannels(); | 151 | VmbusChannelReleaseUnattachedChannels(); |
| 152 | VmbusDisconnect(); | 152 | VmbusDisconnect(); |
| 153 | HvSynicCleanup(); | 153 | on_each_cpu(HvSynicCleanup, NULL, 1); |
| 154 | DPRINT_EXIT(VMBUS); | 154 | DPRINT_EXIT(VMBUS); |
| 155 | 155 | ||
| 156 | return ret; | 156 | return ret; |
| @@ -173,7 +173,8 @@ static void VmbusOnCleanup(struct hv_driver *drv) | |||
| 173 | */ | 173 | */ |
| 174 | static void VmbusOnMsgDPC(struct hv_driver *drv) | 174 | static void VmbusOnMsgDPC(struct hv_driver *drv) |
| 175 | { | 175 | { |
| 176 | void *page_addr = gHvContext.synICMessagePage[0]; | 176 | int cpu = smp_processor_id(); |
| 177 | void *page_addr = gHvContext.synICMessagePage[cpu]; | ||
| 177 | struct hv_message *msg = (struct hv_message *)page_addr + | 178 | struct hv_message *msg = (struct hv_message *)page_addr + |
| 178 | VMBUS_MESSAGE_SINT; | 179 | VMBUS_MESSAGE_SINT; |
| 179 | struct hv_message *copied; | 180 | struct hv_message *copied; |
| @@ -230,11 +231,12 @@ static void VmbusOnEventDPC(struct hv_driver *drv) | |||
| 230 | static int VmbusOnISR(struct hv_driver *drv) | 231 | static int VmbusOnISR(struct hv_driver *drv) |
| 231 | { | 232 | { |
| 232 | int ret = 0; | 233 | int ret = 0; |
| 234 | int cpu = smp_processor_id(); | ||
| 233 | void *page_addr; | 235 | void *page_addr; |
| 234 | struct hv_message *msg; | 236 | struct hv_message *msg; |
| 235 | union hv_synic_event_flags *event; | 237 | union hv_synic_event_flags *event; |
| 236 | 238 | ||
| 237 | page_addr = gHvContext.synICMessagePage[0]; | 239 | page_addr = gHvContext.synICMessagePage[cpu]; |
| 238 | msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; | 240 | msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; |
| 239 | 241 | ||
| 240 | DPRINT_ENTER(VMBUS); | 242 | DPRINT_ENTER(VMBUS); |
| @@ -248,7 +250,7 @@ static int VmbusOnISR(struct hv_driver *drv) | |||
| 248 | } | 250 | } |
| 249 | 251 | ||
| 250 | /* TODO: Check if there are events to be process */ | 252 | /* TODO: Check if there are events to be process */ |
| 251 | page_addr = gHvContext.synICEventPage[0]; | 253 | page_addr = gHvContext.synICEventPage[cpu]; |
| 252 | event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT; | 254 | event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT; |
| 253 | 255 | ||
| 254 | /* Since we are a child, we only need to check bit 0 */ | 256 | /* Since we are a child, we only need to check bit 0 */ |
