Commit 03fbaca3 authored by Bjorn Helgaas's avatar Bjorn Helgaas Committed by Tony Luck

[IA64] update HP CSR space discovery via ACPI

Get rid of the manual search of _CRS, in favor of
acpi_get_vendor_resource() which is now provided by the ACPI CA.  And fall
back to searching for a consumer-only address space descriptor if no
vendor-defined resource is found.
Signed-off-by: default avatarBjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
parent b8cd2af8
/* /*
* arch/ia64/kernel/acpi-ext.c * (c) Copyright 2003, 2006 Hewlett-Packard Development Company, L.P.
* Alex Williamson <alex.williamson@hp.com>
* Bjorn Helgaas <bjorn.helgaas@hp.com>
* *
* Copyright (C) 2003 Hewlett-Packard * This program is free software; you can redistribute it and/or modify
* Copyright (C) Alex Williamson * it under the terms of the GNU General Public License version 2 as
* Copyright (C) Bjorn Helgaas * published by the Free Software Foundation.
*
* Vendor specific extensions to ACPI.
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/efi.h>
#include <asm/acpi-ext.h> #include <asm/acpi-ext.h>
struct acpi_vendor_descriptor { /*
u8 guid_id; * Device CSRs that do not appear in PCI config space should be described
efi_guid_t guid; * 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_info { struct acpi_vendor_uuid hp_ccsr_uuid = {
struct acpi_vendor_descriptor *descriptor; .subtype = 2,
u8 *data; .data = { 0xf9, 0xad, 0xe9, 0x69, 0x4f, 0x92, 0x5f, 0xab, 0xf6, 0x4a,
u32 length; 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad },
}; };
acpi_status static acpi_status hp_ccsr_locate(acpi_handle obj, u64 *base, u64 *length)
acpi_vendor_resource_match(struct acpi_resource *resource, void *context)
{ {
struct acpi_vendor_info *info = (struct acpi_vendor_info *)context; acpi_status status;
struct acpi_resource_vendor *vendor; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_vendor_descriptor *descriptor; struct acpi_resource *resource;
u32 byte_length; struct acpi_resource_vendor_typed *vendor;
if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) status = acpi_get_vendor_resource(obj, METHOD_NAME__CRS, &hp_ccsr_uuid,
return AE_OK; &buffer);
vendor = (struct acpi_resource_vendor *)&resource->data; resource = buffer.pointer;
descriptor = (struct acpi_vendor_descriptor *)vendor->byte_data; vendor = &resource->data.vendor_typed;
if (vendor->byte_length <= sizeof(*info->descriptor) ||
descriptor->guid_id != info->descriptor->guid_id ||
efi_guidcmp(descriptor->guid, info->descriptor->guid))
return AE_OK;
byte_length = vendor->byte_length - sizeof(struct acpi_vendor_descriptor); if (ACPI_FAILURE(status) || vendor->byte_length < 16) {
info->data = acpi_os_allocate(byte_length); status = AE_NOT_FOUND;
if (!info->data) goto exit;
return AE_NO_MEMORY; }
memcpy(info->data, memcpy(base, vendor->byte_data, sizeof(*base));
vendor->byte_data + sizeof(struct acpi_vendor_descriptor), memcpy(length, vendor->byte_data + 8, sizeof(*length));
byte_length);
info->length = byte_length; exit:
return AE_CTRL_TERMINATE; acpi_os_free(buffer.pointer);
return status;
} }
acpi_status struct csr_space {
acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor * id, u64 base;
u8 ** data, u32 * byte_length) u64 length;
};
static acpi_status find_csr_space(struct acpi_resource *resource, void *data)
{ {
struct acpi_vendor_info info; struct csr_space *space = data;
struct acpi_resource_address64 addr;
acpi_status status;
info.descriptor = id; status = acpi_resource_to_address64(resource, &addr);
info.data = NULL; if (ACPI_SUCCESS(status) &&
addr.resource_type == ACPI_MEMORY_RANGE &&
addr.address_length &&
addr.producer_consumer == ACPI_CONSUMER) {
space->base = addr.minimum;
space->length = addr.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, acpi_vendor_resource_match, acpi_walk_resources(obj, METHOD_NAME__CRS, find_csr_space, &space);
&info); if (!space.length)
if (!info.data)
return AE_NOT_FOUND; return AE_NOT_FOUND;
*data = info.data; *base = space.base;
*byte_length = info.length; *length = space.length;
return AE_OK; return AE_OK;
} }
struct acpi_vendor_descriptor hp_ccsr_descriptor = { acpi_status hp_acpi_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length)
.guid_id = 2,
.guid =
EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, 0xf6, 0x4a, 0x24, 0xd2, 0x01,
0x37, 0x0e, 0xad)
};
acpi_status hp_acpi_csr_space(acpi_handle obj, u64 * csr_base, u64 * csr_length)
{ {
acpi_status status; acpi_status status;
u8 *data;
u32 length;
status = status = hp_ccsr_locate(obj, csr_base, csr_length);
acpi_find_vendor_resource(obj, &hp_ccsr_descriptor, &data, &length); if (ACPI_SUCCESS(status))
return status;
if (ACPI_FAILURE(status) || length != 16) return hp_crs_locate(obj, csr_base, csr_length);
return AE_NOT_FOUND;
memcpy(csr_base, data, sizeof(*csr_base));
memcpy(csr_length, data + 8, sizeof(*csr_length));
acpi_os_free(data);
return AE_OK;
} }
EXPORT_SYMBOL(hp_acpi_csr_space); EXPORT_SYMBOL(hp_acpi_csr_space);
/* /*
* ia64/platform/hp/common/hp_acpi.h * (c) Copyright 2003, 2006 Hewlett-Packard Development Company, L.P.
* Alex Williamson <alex.williamson@hp.com>
* Bjorn Helgaas <bjorn.helgaas@hp.com>
* *
* Copyright (C) 2003 Hewlett-Packard * This program is free software; you can redistribute it and/or modify
* Copyright (C) Alex Williamson * it under the terms of the GNU General Public License version 2 as
* Copyright (C) Bjorn Helgaas * published by the Free Software Foundation.
* *
* Vendor specific extensions to ACPI. * Vendor specific extensions to ACPI.
*/ */
#ifndef _ASM_IA64_ACPI_EXT_H #ifndef _ASM_IA64_ACPI_EXT_H
#define _ASM_IA64_ACPI_EXT_H #define _ASM_IA64_ACPI_EXT_H
......
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