Commit 027da541 authored by Jake Oshins's avatar Jake Oshins Committed by Tim Gardner

drivers:hv: Lock access to hyperv_mmio resource tree

BugLink: http://bugs.launchpad.net/bugs/1616677

In existing code, this tree of resources is created
in single-threaded code and never modified after it is
created, and thus needs no locking.  This patch introduces
a semaphore for tree access, as other patches in this
series introduce run-time modifications of this resource
tree which can happen on multiple threads.
Signed-off-by: default avatarJake Oshins <jakeo@microsoft.com>
Signed-off-by: default avatarK. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
(back ported from commit e16dad6b)
Signed-off-by: default avatarTim Gardner <tim.gardner@canonical.com>

 Conflicts:
	drivers/hv/vmbus_drv.c
Acked-by: default avatarBrad Figg <brad.figg@canonical.com>
Acked-by: default avatarKamal Mostafa <kamal@canonical.com>
parent 41d65dae
......@@ -1164,10 +1164,11 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
resource_size_t size, resource_size_t align,
bool fb_overlap_ok)
{
struct resource *iter, *shadow;
resource_size_t range_min, range_max, start;
struct resource *iter;
resource_size_t range_min, range_max, start, local_min, local_max;
const char *dev_n = dev_name(&device_obj->device);
int retval;
u32 fb_end = screen_info.lfb_base + (screen_info.lfb_size << 1);
int i, retval;
retval = -ENXIO;
down(&hyperv_mmio_lock);
......@@ -1198,21 +1199,40 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
range_min = iter->start;
range_max = iter->end;
start = (range_min + align - 1) & ~(align - 1);
for (; start + size - 1 <= range_max; start += align) {
shadow = __request_region(iter, start, size, NULL,
IORESOURCE_BUSY);
if (!shadow)
/* If this range overlaps the frame buffer, split it into
two tries. */
for (i = 0; i < 2; i++) {
local_min = range_min;
local_max = range_max;
if (fb_overlap_ok || (range_min >= fb_end) ||
(range_max <= screen_info.lfb_base)) {
i++;
} else {
if ((range_min <= screen_info.lfb_base) &&
(range_max >= screen_info.lfb_base)) {
/*
* The frame buffer is in this window,
* so trim this into the part that
* preceeds the frame buffer.
*/
local_max = screen_info.lfb_base - 1;
range_min = fb_end;
} else {
range_min = fb_end;
continue;
}
}
*new = request_mem_region_exclusive(start, size, dev_n);
start = (local_min + align - 1) & ~(align - 1);
for (; start + size - 1 <= local_max; start += align) {
*new = request_mem_region_exclusive(start, size,
dev_n);
if (*new) {
shadow->name = (char *)*new;
retval = 0;
goto exit;
}
__release_region(iter, start, size);
}
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment