mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
Merge branches 'acpi-pnp', 'acpi-soc', 'pm-domains' and 'pm-sleep'
* acpi-pnp: ACPI / PNP: Reserve ACPI resources at the fs_initcall_sync stage * acpi-soc: ACPI / LPSS: Fix up acpi_lpss_create_device() * pm-domains: PM / Domains: Avoid infinite loops in attach/detach code * pm-sleep: PM / hibernate: clarify resume documentation
This commit is contained in:
commit
d0aee67fa1
7 changed files with 45 additions and 207 deletions
|
|
@ -352,13 +352,16 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
|
|||
pdata->mmio_size = resource_size(rentry->res);
|
||||
pdata->mmio_base = ioremap(rentry->res->start,
|
||||
pdata->mmio_size);
|
||||
if (!pdata->mmio_base)
|
||||
goto err_out;
|
||||
break;
|
||||
}
|
||||
|
||||
acpi_dev_free_resource_list(&resource_list);
|
||||
|
||||
if (!pdata->mmio_base) {
|
||||
ret = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
pdata->dev_desc = dev_desc;
|
||||
|
||||
if (dev_desc->setup)
|
||||
|
|
|
|||
|
|
@ -175,10 +175,14 @@ static void __init acpi_request_region (struct acpi_generic_address *gas,
|
|||
if (!addr || !length)
|
||||
return;
|
||||
|
||||
acpi_reserve_region(addr, length, gas->space_id, 0, desc);
|
||||
/* Resources are never freed */
|
||||
if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO)
|
||||
request_region(addr, length, desc);
|
||||
else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
|
||||
request_mem_region(addr, length, desc);
|
||||
}
|
||||
|
||||
static void __init acpi_reserve_resources(void)
|
||||
static int __init acpi_reserve_resources(void)
|
||||
{
|
||||
acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length,
|
||||
"ACPI PM1a_EVT_BLK");
|
||||
|
|
@ -207,7 +211,10 @@ static void __init acpi_reserve_resources(void)
|
|||
if (!(acpi_gbl_FADT.gpe1_block_length & 0x1))
|
||||
acpi_request_region(&acpi_gbl_FADT.xgpe1_block,
|
||||
acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK");
|
||||
|
||||
return 0;
|
||||
}
|
||||
fs_initcall_sync(acpi_reserve_resources);
|
||||
|
||||
void acpi_os_printf(const char *fmt, ...)
|
||||
{
|
||||
|
|
@ -1862,7 +1869,6 @@ acpi_status __init acpi_os_initialize(void)
|
|||
|
||||
acpi_status __init acpi_os_initialize1(void)
|
||||
{
|
||||
acpi_reserve_resources();
|
||||
kacpid_wq = alloc_workqueue("kacpid", 0, 1);
|
||||
kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1);
|
||||
kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
|
|
@ -622,164 +621,3 @@ int acpi_dev_filter_resource_type(struct acpi_resource *ares,
|
|||
return (type & types) ? 0 : 1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type);
|
||||
|
||||
struct reserved_region {
|
||||
struct list_head node;
|
||||
u64 start;
|
||||
u64 end;
|
||||
};
|
||||
|
||||
static LIST_HEAD(reserved_io_regions);
|
||||
static LIST_HEAD(reserved_mem_regions);
|
||||
|
||||
static int request_range(u64 start, u64 end, u8 space_id, unsigned long flags,
|
||||
char *desc)
|
||||
{
|
||||
unsigned int length = end - start + 1;
|
||||
struct resource *res;
|
||||
|
||||
res = space_id == ACPI_ADR_SPACE_SYSTEM_IO ?
|
||||
request_region(start, length, desc) :
|
||||
request_mem_region(start, length, desc);
|
||||
if (!res)
|
||||
return -EIO;
|
||||
|
||||
res->flags &= ~flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int add_region_before(u64 start, u64 end, u8 space_id,
|
||||
unsigned long flags, char *desc,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct reserved_region *reg;
|
||||
int error;
|
||||
|
||||
reg = kmalloc(sizeof(*reg), GFP_KERNEL);
|
||||
if (!reg)
|
||||
return -ENOMEM;
|
||||
|
||||
error = request_range(start, end, space_id, flags, desc);
|
||||
if (error) {
|
||||
kfree(reg);
|
||||
return error;
|
||||
}
|
||||
|
||||
reg->start = start;
|
||||
reg->end = end;
|
||||
list_add_tail(®->node, head);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_reserve_region - Reserve an I/O or memory region as a system resource.
|
||||
* @start: Starting address of the region.
|
||||
* @length: Length of the region.
|
||||
* @space_id: Identifier of address space to reserve the region from.
|
||||
* @flags: Resource flags to clear for the region after requesting it.
|
||||
* @desc: Region description (for messages).
|
||||
*
|
||||
* Reserve an I/O or memory region as a system resource to prevent others from
|
||||
* using it. If the new region overlaps with one of the regions (in the given
|
||||
* address space) already reserved by this routine, only the non-overlapping
|
||||
* parts of it will be reserved.
|
||||
*
|
||||
* Returned is either 0 (success) or a negative error code indicating a resource
|
||||
* reservation problem. It is the code of the first encountered error, but the
|
||||
* routine doesn't abort until it has attempted to request all of the parts of
|
||||
* the new region that don't overlap with other regions reserved previously.
|
||||
*
|
||||
* The resources requested by this routine are never released.
|
||||
*/
|
||||
int acpi_reserve_region(u64 start, unsigned int length, u8 space_id,
|
||||
unsigned long flags, char *desc)
|
||||
{
|
||||
struct list_head *regions;
|
||||
struct reserved_region *reg;
|
||||
u64 end = start + length - 1;
|
||||
int ret = 0, error = 0;
|
||||
|
||||
if (space_id == ACPI_ADR_SPACE_SYSTEM_IO)
|
||||
regions = &reserved_io_regions;
|
||||
else if (space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
|
||||
regions = &reserved_mem_regions;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (list_empty(regions))
|
||||
return add_region_before(start, end, space_id, flags, desc, regions);
|
||||
|
||||
list_for_each_entry(reg, regions, node)
|
||||
if (reg->start == end + 1) {
|
||||
/* The new region can be prepended to this one. */
|
||||
ret = request_range(start, end, space_id, flags, desc);
|
||||
if (!ret)
|
||||
reg->start = start;
|
||||
|
||||
return ret;
|
||||
} else if (reg->start > end) {
|
||||
/* No overlap. Add the new region here and get out. */
|
||||
return add_region_before(start, end, space_id, flags,
|
||||
desc, ®->node);
|
||||
} else if (reg->end == start - 1) {
|
||||
goto combine;
|
||||
} else if (reg->end >= start) {
|
||||
goto overlap;
|
||||
}
|
||||
|
||||
/* The new region goes after the last existing one. */
|
||||
return add_region_before(start, end, space_id, flags, desc, regions);
|
||||
|
||||
overlap:
|
||||
/*
|
||||
* The new region overlaps an existing one.
|
||||
*
|
||||
* The head part of the new region immediately preceding the existing
|
||||
* overlapping one can be combined with it right away.
|
||||
*/
|
||||
if (reg->start > start) {
|
||||
error = request_range(start, reg->start - 1, space_id, flags, desc);
|
||||
if (error)
|
||||
ret = error;
|
||||
else
|
||||
reg->start = start;
|
||||
}
|
||||
|
||||
combine:
|
||||
/*
|
||||
* The new region is adjacent to an existing one. If it extends beyond
|
||||
* that region all the way to the next one, it is possible to combine
|
||||
* all three of them.
|
||||
*/
|
||||
while (reg->end < end) {
|
||||
struct reserved_region *next = NULL;
|
||||
u64 a = reg->end + 1, b = end;
|
||||
|
||||
if (!list_is_last(®->node, regions)) {
|
||||
next = list_next_entry(reg, node);
|
||||
if (next->start <= end)
|
||||
b = next->start - 1;
|
||||
}
|
||||
error = request_range(a, b, space_id, flags, desc);
|
||||
if (!error) {
|
||||
if (next && next->start == b + 1) {
|
||||
reg->end = next->end;
|
||||
list_del(&next->node);
|
||||
kfree(next);
|
||||
} else {
|
||||
reg->end = end;
|
||||
break;
|
||||
}
|
||||
} else if (next) {
|
||||
if (!ret)
|
||||
ret = error;
|
||||
|
||||
reg = next;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret ? ret : error;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_reserve_region);
|
||||
|
|
|
|||
Loading…
Reference in a new issue