mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
Merge branch 'acpi-pci'
* acpi-pci: ia64/PCI/ACPI: Use common interface to support PCI host bridge x86/PCI/ACPI: Use common interface to support PCI host bridge ACPI/PCI: Reset acpi_root_dev->domain to 0 when pci_ignore_seg is set PCI/ACPI: Add interface acpi_pci_root_create() ia64/PCI: Use common struct resource_entry to replace struct iospace_resource ia64/PCI/ACPI: Use common ACPI resource parsing interface for host bridge ACPI/PCI: Enhance ACPI core to support sparse IO space
This commit is contained in:
commit
ba210f5de4
7 changed files with 423 additions and 484 deletions
|
|
@ -652,6 +652,210 @@ static void acpi_pci_root_remove(struct acpi_device *device)
|
|||
kfree(root);
|
||||
}
|
||||
|
||||
/*
|
||||
* Following code to support acpi_pci_root_create() is copied from
|
||||
* arch/x86/pci/acpi.c and modified so it could be reused by x86, IA64
|
||||
* and ARM64.
|
||||
*/
|
||||
static void acpi_pci_root_validate_resources(struct device *dev,
|
||||
struct list_head *resources,
|
||||
unsigned long type)
|
||||
{
|
||||
LIST_HEAD(list);
|
||||
struct resource *res1, *res2, *root = NULL;
|
||||
struct resource_entry *tmp, *entry, *entry2;
|
||||
|
||||
BUG_ON((type & (IORESOURCE_MEM | IORESOURCE_IO)) == 0);
|
||||
root = (type & IORESOURCE_MEM) ? &iomem_resource : &ioport_resource;
|
||||
|
||||
list_splice_init(resources, &list);
|
||||
resource_list_for_each_entry_safe(entry, tmp, &list) {
|
||||
bool free = false;
|
||||
resource_size_t end;
|
||||
|
||||
res1 = entry->res;
|
||||
if (!(res1->flags & type))
|
||||
goto next;
|
||||
|
||||
/* Exclude non-addressable range or non-addressable portion */
|
||||
end = min(res1->end, root->end);
|
||||
if (end <= res1->start) {
|
||||
dev_info(dev, "host bridge window %pR (ignored, not CPU addressable)\n",
|
||||
res1);
|
||||
free = true;
|
||||
goto next;
|
||||
} else if (res1->end != end) {
|
||||
dev_info(dev, "host bridge window %pR ([%#llx-%#llx] ignored, not CPU addressable)\n",
|
||||
res1, (unsigned long long)end + 1,
|
||||
(unsigned long long)res1->end);
|
||||
res1->end = end;
|
||||
}
|
||||
|
||||
resource_list_for_each_entry(entry2, resources) {
|
||||
res2 = entry2->res;
|
||||
if (!(res2->flags & type))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* I don't like throwing away windows because then
|
||||
* our resources no longer match the ACPI _CRS, but
|
||||
* the kernel resource tree doesn't allow overlaps.
|
||||
*/
|
||||
if (resource_overlaps(res1, res2)) {
|
||||
res2->start = min(res1->start, res2->start);
|
||||
res2->end = max(res1->end, res2->end);
|
||||
dev_info(dev, "host bridge window expanded to %pR; %pR ignored\n",
|
||||
res2, res1);
|
||||
free = true;
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
next:
|
||||
resource_list_del(entry);
|
||||
if (free)
|
||||
resource_list_free_entry(entry);
|
||||
else
|
||||
resource_list_add_tail(entry, resources);
|
||||
}
|
||||
}
|
||||
|
||||
int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
|
||||
{
|
||||
int ret;
|
||||
struct list_head *list = &info->resources;
|
||||
struct acpi_device *device = info->bridge;
|
||||
struct resource_entry *entry, *tmp;
|
||||
unsigned long flags;
|
||||
|
||||
flags = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT;
|
||||
ret = acpi_dev_get_resources(device, list,
|
||||
acpi_dev_filter_resource_type_cb,
|
||||
(void *)flags);
|
||||
if (ret < 0)
|
||||
dev_warn(&device->dev,
|
||||
"failed to parse _CRS method, error code %d\n", ret);
|
||||
else if (ret == 0)
|
||||
dev_dbg(&device->dev,
|
||||
"no IO and memory resources present in _CRS\n");
|
||||
else {
|
||||
resource_list_for_each_entry_safe(entry, tmp, list) {
|
||||
if (entry->res->flags & IORESOURCE_DISABLED)
|
||||
resource_list_destroy_entry(entry);
|
||||
else
|
||||
entry->res->name = info->name;
|
||||
}
|
||||
acpi_pci_root_validate_resources(&device->dev, list,
|
||||
IORESOURCE_MEM);
|
||||
acpi_pci_root_validate_resources(&device->dev, list,
|
||||
IORESOURCE_IO);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void pci_acpi_root_add_resources(struct acpi_pci_root_info *info)
|
||||
{
|
||||
struct resource_entry *entry, *tmp;
|
||||
struct resource *res, *conflict, *root = NULL;
|
||||
|
||||
resource_list_for_each_entry_safe(entry, tmp, &info->resources) {
|
||||
res = entry->res;
|
||||
if (res->flags & IORESOURCE_MEM)
|
||||
root = &iomem_resource;
|
||||
else if (res->flags & IORESOURCE_IO)
|
||||
root = &ioport_resource;
|
||||
else
|
||||
continue;
|
||||
|
||||
conflict = insert_resource_conflict(root, res);
|
||||
if (conflict) {
|
||||
dev_info(&info->bridge->dev,
|
||||
"ignoring host bridge window %pR (conflicts with %s %pR)\n",
|
||||
res, conflict->name, conflict);
|
||||
resource_list_destroy_entry(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void __acpi_pci_root_release_info(struct acpi_pci_root_info *info)
|
||||
{
|
||||
struct resource *res;
|
||||
struct resource_entry *entry, *tmp;
|
||||
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
resource_list_for_each_entry_safe(entry, tmp, &info->resources) {
|
||||
res = entry->res;
|
||||
if (res->parent &&
|
||||
(res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
|
||||
release_resource(res);
|
||||
resource_list_destroy_entry(entry);
|
||||
}
|
||||
|
||||
info->ops->release_info(info);
|
||||
}
|
||||
|
||||
static void acpi_pci_root_release_info(struct pci_host_bridge *bridge)
|
||||
{
|
||||
struct resource *res;
|
||||
struct resource_entry *entry;
|
||||
|
||||
resource_list_for_each_entry(entry, &bridge->windows) {
|
||||
res = entry->res;
|
||||
if (res->parent &&
|
||||
(res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
|
||||
release_resource(res);
|
||||
}
|
||||
__acpi_pci_root_release_info(bridge->release_data);
|
||||
}
|
||||
|
||||
struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
|
||||
struct acpi_pci_root_ops *ops,
|
||||
struct acpi_pci_root_info *info,
|
||||
void *sysdata)
|
||||
{
|
||||
int ret, busnum = root->secondary.start;
|
||||
struct acpi_device *device = root->device;
|
||||
int node = acpi_get_node(device->handle);
|
||||
struct pci_bus *bus;
|
||||
|
||||
info->root = root;
|
||||
info->bridge = device;
|
||||
info->ops = ops;
|
||||
INIT_LIST_HEAD(&info->resources);
|
||||
snprintf(info->name, sizeof(info->name), "PCI Bus %04x:%02x",
|
||||
root->segment, busnum);
|
||||
|
||||
if (ops->init_info && ops->init_info(info))
|
||||
goto out_release_info;
|
||||
if (ops->prepare_resources)
|
||||
ret = ops->prepare_resources(info);
|
||||
else
|
||||
ret = acpi_pci_probe_root_resources(info);
|
||||
if (ret < 0)
|
||||
goto out_release_info;
|
||||
|
||||
pci_acpi_root_add_resources(info);
|
||||
pci_add_resource(&info->resources, &root->secondary);
|
||||
bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
|
||||
sysdata, &info->resources);
|
||||
if (!bus)
|
||||
goto out_release_info;
|
||||
|
||||
pci_scan_child_bus(bus);
|
||||
pci_set_host_bridge_release(to_pci_host_bridge(bus->bridge),
|
||||
acpi_pci_root_release_info, info);
|
||||
if (node != NUMA_NO_NODE)
|
||||
dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node);
|
||||
return bus;
|
||||
|
||||
out_release_info:
|
||||
__acpi_pci_root_release_info(info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void __init acpi_pci_root_init(void)
|
||||
{
|
||||
acpi_hest_init();
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
|
|||
EXPORT_SYMBOL_GPL(acpi_dev_resource_memory);
|
||||
|
||||
static void acpi_dev_ioresource_flags(struct resource *res, u64 len,
|
||||
u8 io_decode)
|
||||
u8 io_decode, u8 translation_type)
|
||||
{
|
||||
res->flags = IORESOURCE_IO;
|
||||
|
||||
|
|
@ -131,6 +131,8 @@ static void acpi_dev_ioresource_flags(struct resource *res, u64 len,
|
|||
|
||||
if (io_decode == ACPI_DECODE_16)
|
||||
res->flags |= IORESOURCE_IO_16BIT_ADDR;
|
||||
if (translation_type == ACPI_SPARSE_TRANSLATION)
|
||||
res->flags |= IORESOURCE_IO_SPARSE;
|
||||
}
|
||||
|
||||
static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
|
||||
|
|
@ -138,7 +140,7 @@ static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
|
|||
{
|
||||
res->start = start;
|
||||
res->end = start + len - 1;
|
||||
acpi_dev_ioresource_flags(res, len, io_decode);
|
||||
acpi_dev_ioresource_flags(res, len, io_decode, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -231,7 +233,8 @@ static bool acpi_decode_space(struct resource_win *win,
|
|||
acpi_dev_memresource_flags(res, len, wp);
|
||||
break;
|
||||
case ACPI_IO_RANGE:
|
||||
acpi_dev_ioresource_flags(res, len, iodec);
|
||||
acpi_dev_ioresource_flags(res, len, iodec,
|
||||
addr->info.io.translation_type);
|
||||
break;
|
||||
case ACPI_BUS_NUMBER_RANGE:
|
||||
res->flags = IORESOURCE_BUS;
|
||||
|
|
|
|||
Loading…
Reference in a new issue