summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hv/vmbus_drv.c37
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
46static struct acpi_device *hv_acpi_dev; 47static 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
105static const char *fb_mmio_name = "fb_range";
106static struct resource *fb_mmio;
104struct resource *hyperv_mmio; 107struct resource *hyperv_mmio;
105DEFINE_SEMAPHORE(hyperv_mmio_lock); 108DEFINE_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
1112static 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