summaryrefslogtreecommitdiffstats
path: root/drivers/hv
diff options
context:
space:
mode:
authorJake Oshins <jakeo@microsoft.com>2016-04-05 13:22:55 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-04-30 17:01:37 -0400
commit6d146aefbaa5c5dff0c2e9d81e90e5112ded284e (patch)
tree46298ca68d1d1c0edd9bcf75e61118fa1324611b /drivers/hv
parentbe000f93e5d71f5d43dd722f8eb110b069f9d8a2 (diff)
drivers:hv: Record MMIO range in use by frame buffer
Later in the boot sequence, we need to figure out which memory ranges can be given out to various paravirtual drivers. The hyperv_fb driver should, ideally, be placed right on top of the frame buffer, without some other device getting plopped on top of this range in the meantime. Recording this now allows that to be guaranteed. Signed-off-by: Jake Oshins <jakeo@microsoft.com> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hv')
-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