diff options
-rw-r--r-- | drivers/hv/vmbus_drv.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index dfc6149ccc93..eaa5c3b7fd8a 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/ptrace.h> | 41 | #include <linux/ptrace.h> |
42 | #include <linux/screen_info.h> | 42 | #include <linux/screen_info.h> |
43 | #include <linux/kdebug.h> | 43 | #include <linux/kdebug.h> |
44 | #include <linux/efi.h> | ||
44 | #include "hyperv_vmbus.h" | 45 | #include "hyperv_vmbus.h" |
45 | 46 | ||
46 | static struct acpi_device *hv_acpi_dev; | 47 | static struct acpi_device *hv_acpi_dev; |
@@ -101,6 +102,8 @@ static struct notifier_block hyperv_panic_block = { | |||
101 | .notifier_call = hyperv_panic_event, | 102 | .notifier_call = hyperv_panic_event, |
102 | }; | 103 | }; |
103 | 104 | ||
105 | static const char *fb_mmio_name = "fb_range"; | ||
106 | static struct resource *fb_mmio; | ||
104 | struct resource *hyperv_mmio; | 107 | struct resource *hyperv_mmio; |
105 | DEFINE_SEMAPHORE(hyperv_mmio_lock); | 108 | DEFINE_SEMAPHORE(hyperv_mmio_lock); |
106 | 109 | ||
@@ -1091,6 +1094,12 @@ static int vmbus_acpi_remove(struct acpi_device *device) | |||
1091 | struct resource *next_res; | 1094 | struct resource *next_res; |
1092 | 1095 | ||
1093 | if (hyperv_mmio) { | 1096 | if (hyperv_mmio) { |
1097 | if (fb_mmio) { | ||
1098 | __release_region(hyperv_mmio, fb_mmio->start, | ||
1099 | resource_size(fb_mmio)); | ||
1100 | fb_mmio = NULL; | ||
1101 | } | ||
1102 | |||
1094 | for (cur_res = hyperv_mmio; cur_res; cur_res = next_res) { | 1103 | for (cur_res = hyperv_mmio; cur_res; cur_res = next_res) { |
1095 | next_res = cur_res->sibling; | 1104 | next_res = cur_res->sibling; |
1096 | kfree(cur_res); | 1105 | kfree(cur_res); |
@@ -1100,6 +1109,30 @@ static int vmbus_acpi_remove(struct acpi_device *device) | |||
1100 | return 0; | 1109 | return 0; |
1101 | } | 1110 | } |
1102 | 1111 | ||
1112 | static void vmbus_reserve_fb(void) | ||
1113 | { | ||
1114 | int size; | ||
1115 | /* | ||
1116 | * Make a claim for the frame buffer in the resource tree under the | ||
1117 | * first node, which will be the one below 4GB. The length seems to | ||
1118 | * be underreported, particularly in a Generation 1 VM. So start out | ||
1119 | * reserving a larger area and make it smaller until it succeeds. | ||
1120 | */ | ||
1121 | |||
1122 | if (screen_info.lfb_base) { | ||
1123 | if (efi_enabled(EFI_BOOT)) | ||
1124 | size = max_t(__u32, screen_info.lfb_size, 0x800000); | ||
1125 | else | ||
1126 | size = max_t(__u32, screen_info.lfb_size, 0x4000000); | ||
1127 | |||
1128 | for (; !fb_mmio && (size >= 0x100000); size >>= 1) { | ||
1129 | fb_mmio = __request_region(hyperv_mmio, | ||
1130 | screen_info.lfb_base, size, | ||
1131 | fb_mmio_name, 0); | ||
1132 | } | ||
1133 | } | ||
1134 | } | ||
1135 | |||
1103 | /** | 1136 | /** |
1104 | * vmbus_allocate_mmio() - Pick a memory-mapped I/O range. | 1137 | * vmbus_allocate_mmio() - Pick a memory-mapped I/O range. |
1105 | * @new: If successful, supplied a pointer to the | 1138 | * @new: If successful, supplied a pointer to the |
@@ -1261,8 +1294,10 @@ static int vmbus_acpi_add(struct acpi_device *device) | |||
1261 | 1294 | ||
1262 | if (ACPI_FAILURE(result)) | 1295 | if (ACPI_FAILURE(result)) |
1263 | continue; | 1296 | continue; |
1264 | if (hyperv_mmio) | 1297 | if (hyperv_mmio) { |
1298 | vmbus_reserve_fb(); | ||
1265 | break; | 1299 | break; |
1300 | } | ||
1266 | } | 1301 | } |
1267 | ret_val = 0; | 1302 | ret_val = 0; |
1268 | 1303 | ||