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>
This commit is contained in:
parent
be000f93e5
commit
6d146aefba
|
@ -41,6 +41,7 @@
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
#include <linux/screen_info.h>
|
#include <linux/screen_info.h>
|
||||||
#include <linux/kdebug.h>
|
#include <linux/kdebug.h>
|
||||||
|
#include <linux/efi.h>
|
||||||
#include "hyperv_vmbus.h"
|
#include "hyperv_vmbus.h"
|
||||||
|
|
||||||
static struct acpi_device *hv_acpi_dev;
|
static struct acpi_device *hv_acpi_dev;
|
||||||
|
@ -101,6 +102,8 @@ static struct notifier_block hyperv_panic_block = {
|
||||||
.notifier_call = hyperv_panic_event,
|
.notifier_call = hyperv_panic_event,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char *fb_mmio_name = "fb_range";
|
||||||
|
static struct resource *fb_mmio;
|
||||||
struct resource *hyperv_mmio;
|
struct resource *hyperv_mmio;
|
||||||
DEFINE_SEMAPHORE(hyperv_mmio_lock);
|
DEFINE_SEMAPHORE(hyperv_mmio_lock);
|
||||||
|
|
||||||
|
@ -1091,6 +1094,12 @@ static int vmbus_acpi_remove(struct acpi_device *device)
|
||||||
struct resource *next_res;
|
struct resource *next_res;
|
||||||
|
|
||||||
if (hyperv_mmio) {
|
if (hyperv_mmio) {
|
||||||
|
if (fb_mmio) {
|
||||||
|
__release_region(hyperv_mmio, fb_mmio->start,
|
||||||
|
resource_size(fb_mmio));
|
||||||
|
fb_mmio = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
for (cur_res = hyperv_mmio; cur_res; cur_res = next_res) {
|
for (cur_res = hyperv_mmio; cur_res; cur_res = next_res) {
|
||||||
next_res = cur_res->sibling;
|
next_res = cur_res->sibling;
|
||||||
kfree(cur_res);
|
kfree(cur_res);
|
||||||
|
@ -1100,6 +1109,30 @@ static int vmbus_acpi_remove(struct acpi_device *device)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vmbus_reserve_fb(void)
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
/*
|
||||||
|
* Make a claim for the frame buffer in the resource tree under the
|
||||||
|
* first node, which will be the one below 4GB. The length seems to
|
||||||
|
* be underreported, particularly in a Generation 1 VM. So start out
|
||||||
|
* reserving a larger area and make it smaller until it succeeds.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (screen_info.lfb_base) {
|
||||||
|
if (efi_enabled(EFI_BOOT))
|
||||||
|
size = max_t(__u32, screen_info.lfb_size, 0x800000);
|
||||||
|
else
|
||||||
|
size = max_t(__u32, screen_info.lfb_size, 0x4000000);
|
||||||
|
|
||||||
|
for (; !fb_mmio && (size >= 0x100000); size >>= 1) {
|
||||||
|
fb_mmio = __request_region(hyperv_mmio,
|
||||||
|
screen_info.lfb_base, size,
|
||||||
|
fb_mmio_name, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vmbus_allocate_mmio() - Pick a memory-mapped I/O range.
|
* vmbus_allocate_mmio() - Pick a memory-mapped I/O range.
|
||||||
* @new: If successful, supplied a pointer to the
|
* @new: If successful, supplied a pointer to the
|
||||||
|
@ -1261,9 +1294,11 @@ static int vmbus_acpi_add(struct acpi_device *device)
|
||||||
|
|
||||||
if (ACPI_FAILURE(result))
|
if (ACPI_FAILURE(result))
|
||||||
continue;
|
continue;
|
||||||
if (hyperv_mmio)
|
if (hyperv_mmio) {
|
||||||
|
vmbus_reserve_fb();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ret_val = 0;
|
ret_val = 0;
|
||||||
|
|
||||||
acpi_walk_err:
|
acpi_walk_err:
|
||||||
|
|
Loading…
Reference in New Issue