alistair23-linux/arch/ia64/kernel/acpi-ext.c
Lv Zheng a45de93eb1 ACPICA: Resources: Provide common part for struct acpi_resource_address structures.
struct acpi_resource_address and struct acpi_resource_extended_address64 share substracts
just at different offsets. To unify the parsing functions, OSPMs like Linux
need a new ACPI_ADDRESS64_ATTRIBUTE as their substructs, so they can
extract the shared data.

This patch also synchronizes the structure changes to the Linux kernel.
The usages are searched by matching the following keywords:
1. acpi_resource_address
2. acpi_resource_extended_address
3. ACPI_RESOURCE_TYPE_ADDRESS
4. ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS
And we found and fixed the usages in the following files:
 arch/ia64/kernel/acpi-ext.c
 arch/ia64/pci/pci.c
 arch/x86/pci/acpi.c
 arch/x86/pci/mmconfig-shared.c
 drivers/xen/xen-acpi-memhotplug.c
 drivers/acpi/acpi_memhotplug.c
 drivers/acpi/pci_root.c
 drivers/acpi/resource.c
 drivers/char/hpet.c
 drivers/pnp/pnpacpi/rsparser.c
 drivers/hv/vmbus_drv.c

Build tests are passed with defconfig/allnoconfig/allyesconfig and
defconfig+CONFIG_ACPI=n.

Original-by: Thomas Gleixner <tglx@linutronix.de>
Original-by: Jiang Liu <jiang.liu@linux.intel.com>
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-01-26 16:09:56 +01:00

105 lines
2.8 KiB
C

/*
* (c) Copyright 2003, 2006 Hewlett-Packard Development Company, L.P.
* Alex Williamson <alex.williamson@hp.com>
* Bjorn Helgaas <bjorn.helgaas@hp.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <asm/acpi-ext.h>
/*
* Device CSRs that do not appear in PCI config space should be described
* via ACPI. This would normally be done with Address Space Descriptors
* marked as "consumer-only," but old versions of Windows and Linux ignore
* the producer/consumer flag, so HP invented a vendor-defined resource to
* describe the location and size of CSR space.
*/
struct acpi_vendor_uuid hp_ccsr_uuid = {
.subtype = 2,
.data = { 0xf9, 0xad, 0xe9, 0x69, 0x4f, 0x92, 0x5f, 0xab, 0xf6, 0x4a,
0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad },
};
static acpi_status hp_ccsr_locate(acpi_handle obj, u64 *base, u64 *length)
{
acpi_status status;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_resource *resource;
struct acpi_resource_vendor_typed *vendor;
status = acpi_get_vendor_resource(obj, METHOD_NAME__CRS, &hp_ccsr_uuid,
&buffer);
resource = buffer.pointer;
vendor = &resource->data.vendor_typed;
if (ACPI_FAILURE(status) || vendor->byte_length < 16) {
status = AE_NOT_FOUND;
goto exit;
}
memcpy(base, vendor->byte_data, sizeof(*base));
memcpy(length, vendor->byte_data + 8, sizeof(*length));
exit:
kfree(buffer.pointer);
return status;
}
struct csr_space {
u64 base;
u64 length;
};
static acpi_status find_csr_space(struct acpi_resource *resource, void *data)
{
struct csr_space *space = data;
struct acpi_resource_address64 addr;
acpi_status status;
status = acpi_resource_to_address64(resource, &addr);
if (ACPI_SUCCESS(status) &&
addr.resource_type == ACPI_MEMORY_RANGE &&
addr.address.address_length &&
addr.producer_consumer == ACPI_CONSUMER) {
space->base = addr.address.minimum;
space->length = addr.address.address_length;
return AE_CTRL_TERMINATE;
}
return AE_OK; /* keep looking */
}
static acpi_status hp_crs_locate(acpi_handle obj, u64 *base, u64 *length)
{
struct csr_space space = { 0, 0 };
acpi_walk_resources(obj, METHOD_NAME__CRS, find_csr_space, &space);
if (!space.length)
return AE_NOT_FOUND;
*base = space.base;
*length = space.length;
return AE_OK;
}
acpi_status hp_acpi_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length)
{
acpi_status status;
status = hp_ccsr_locate(obj, csr_base, csr_length);
if (ACPI_SUCCESS(status))
return status;
return hp_crs_locate(obj, csr_base, csr_length);
}
EXPORT_SYMBOL(hp_acpi_csr_space);