Mercurial > illumos > illumos-gate
changeset 4951:72d3704b0e71
6505165 pciehpc looking for _SUN on the wrong node
6525527 pciehpc doesn't do pcie native hotplug
author | prasad |
---|---|
date | Mon, 27 Aug 2007 14:40:46 -0700 |
parents | a7a707716fea |
children | a610b3d5cfbb |
files | usr/src/uts/intel/io/hotplug/pciehpc/pciehpc_acpi.c usr/src/uts/intel/io/hotplug/pciehpc/pciehpc_acpi.h |
diffstat | 2 files changed, 177 insertions(+), 76 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/intel/io/hotplug/pciehpc/pciehpc_acpi.c Mon Aug 27 14:04:30 2007 -0700 +++ b/usr/src/uts/intel/io/hotplug/pciehpc/pciehpc_acpi.c Mon Aug 27 14:40:46 2007 -0700 @@ -62,10 +62,10 @@ void *context); static ACPI_STATUS pciehpc_acpi_ej0_present(ACPI_HANDLE pcibus_obj); static ACPI_STATUS pciehpc_acpi_get_dev_state(ACPI_HANDLE obj, int *statusp); -static ACPI_STATUS pciehpc_acpi_query_osc(dev_info_t *dip, ACPI_HANDLE osc_hdl, +static ACPI_STATUS pciehpc_acpi_eval_osc(ACPI_HANDLE osc_hdl, uint32_t *hp_mode); -static ACPI_STATUS pciehpc_acpi_set_native_hp(dev_info_t *dip, - ACPI_HANDLE osc_hdl); +static ACPI_STATUS pciehpc_acpi_find_osc(ACPI_HANDLE busobj, + ACPI_HANDLE *osc_hdlp); #ifdef DEBUG static void pciehpc_dump_acpi_obj(ACPI_HANDLE pcibus_obj); @@ -76,9 +76,6 @@ static void print_acpi_pathname(ACPI_HANDLE hdl); #endif -#define ACPI_HP_MODE 1 -#define NATIVE_HP_MODE 2 - /* UUID for for PCI/PCI-X/PCI-Exp hierarchy as defined in PCI fw ver 3.0 */ static uint8_t pcie_uuid[16] = {0x5b, 0x4d, 0xdb, 0x33, 0xf7, 0x1f, 0x1c, 0x40, @@ -120,65 +117,69 @@ */ PCIEHPC_DEBUG((CE_CONT, "No ACPI device found (dip %p)\n", (void *)dip)); + PCIEHPC_DEBUG((CE_CONT, "Assuming native Hot-Plug mode\n")); return (0); } - /* - * If "use-native-hotplug-mode" property exists then it will tell us - * if we need to switch to or assume native hot plug mode on the - * platform. - */ - if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, - "use-native-hotplug-mode", &hotplug_mode, &count) == - DDI_PROP_SUCCESS) { - if (hotplug_mode[0] == 1) - use_native_hotplug = 1; - ddi_prop_free(hotplug_mode); - } /* * NOTE: Without _OSC method there is no reliable way to know if the * platform implements ACPI hot plug or native hot plug. But, if it is * present then it may be possible to use either mode (i.e ACPI or - * native-hotplug) if the platform supports. + * native-hotplug) if the platform supports both. */ /* - * (2) Check if the node has _OSC method present. + * (2) Check if _OSC method is present. */ - if (AcpiGetHandle(pcibus_obj, "_OSC", &osc_hdl) != AE_OK) { + if (pciehpc_acpi_find_osc(pcibus_obj, &osc_hdl) != AE_OK) { /* no _OSC method present; we need to guess here! */ - if (use_native_hotplug) + PCIEHPC_DEBUG((CE_NOTE, "no _OSC method present\n")); + /* + * If "use-native-hotplug-mode" property set then it means + * the platform supports only native hot-plug mode. + */ + if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, + DDI_PROP_DONTPASS, "use-native-hotplug-mode", + &hotplug_mode, &count) == DDI_PROP_SUCCESS) { + if (hotplug_mode[0] == 1) + use_native_hotplug = 1; + ddi_prop_free(hotplug_mode); + } + if (use_native_hotplug) { + PCIEHPC_DEBUG((CE_NOTE, + "Assuming native Hot-Plug mode\n")); return (0); /* assume native hot plug mode */ - else + } else { + PCIEHPC_DEBUG((CE_NOTE, + "Assuming legacy ACPI Hot-Plug mode\n")); return (1); /* assume ACPI hot plug mode */ + } } /* - * (3) _OSC method exists; check if the current mode is ACPI hot plug. + * (3) _OSC method exists; evaluate _OSC to use native hot-plug mode. + * + * Note: The default policy is to use native hot-plug mode if the + * platform supports it. */ - if (pciehpc_acpi_query_osc(dip, osc_hdl, &hp_mode) != AE_OK) { - /* failed to query _OSC method; assume ACPI hot plug */ + if (pciehpc_acpi_eval_osc(osc_hdl, &hp_mode) != AE_OK) { + /* failed to evaluate _OSC method; assume ACPI hot plug */ + PCIEHPC_DEBUG((CE_NOTE, "Failed to evaluate _OSC; " + "Assuming legacy ACPI Hot-Plug mode\n")); return (1); } - if (hp_mode == NATIVE_HP_MODE) - return (0); /* it is in native hp mode! */ - - if (use_native_hotplug) { - /* try to switch to native hot plug mode */ - if (pciehpc_acpi_set_native_hp(dip, osc_hdl) == AE_OK) { - PCIEHPC_DEBUG((CE_NOTE, "using native hot plug mode\n")); - return (0); /* switched to native hot plug mode */ - } - /* failed to switch to native hp mode */ - PCIEHPC_DEBUG((CE_NOTE, "failed to switch to native" - " hot plug mode; using ACPI mode\n")); - } #ifdef DEBUG if (pciehpc_debug > 1) pciehpc_dump_acpi_obj(pcibus_obj); #endif + if (hp_mode == NATIVE_HP_MODE) { + PCIEHPC_DEBUG((CE_NOTE, "Native Hot-Plug mode enabled\n")); + return (0); /* it is in native hp mode! */ + } + + PCIEHPC_DEBUG((CE_NOTE, "ACPI Hot-Plug mode enabled\n")); return (1); /* use ACPI mode */ } @@ -232,8 +233,8 @@ bus_methods |= PCIEHPC_ACPI_HPP_PRESENT; if (AcpiGetHandle(pcibus_obj, "_DSM", &hdl) == AE_OK) bus_methods |= PCIEHPC_ACPI_DSM_PRESENT; - if (AcpiGetHandle(pcibus_obj, "_SUN", &hdl) == AE_OK) - bus_methods |= PCIEHPC_ACPI_SUN_PRESENT; + if (AcpiGetHandle(slot_dev_obj, "_SUN", &hdl) == AE_OK) + slot_methods |= PCIEHPC_ACPI_SUN_PRESENT; if (AcpiGetHandle(slot_dev_obj, "_PS0", &hdl) == AE_OK) slot_methods |= PCIEHPC_ACPI_PS0_PRESENT; if (AcpiGetHandle(slot_dev_obj, "_EJ0", &hdl) == AE_OK) @@ -758,25 +759,88 @@ } /* - * Query _OSC method to find out the current hot plug mode. + * Evaluate _OSC method to use native hot-plug mode if platform supports it. + * If platform doesn't support native hot-plug then hp_mode will be set + * to ACPI_HP_MODE. */ -/*ARGSUSED*/ static ACPI_STATUS -pciehpc_acpi_query_osc(dev_info_t *dip, ACPI_HANDLE osc_hdl, uint32_t *hp_mode) +pciehpc_acpi_eval_osc(ACPI_HANDLE osc_hdl, uint32_t *hp_mode) { - /* NOTE: This is currently not implemented */ - return (AE_ERROR); -} + ACPI_STATUS status; + ACPI_OBJECT_LIST arglist; + ACPI_OBJECT args[4]; + UINT32 caps_buffer[3]; + ACPI_BUFFER rb; + ACPI_OBJECT *rv; + UINT32 *rbuf; + + /* construct argument list */ + arglist.Count = 4; + arglist.Pointer = args; + + /* arg0 - UUID */ + args[0].Type = ACPI_TYPE_BUFFER; + args[0].Buffer.Length = 16; /* size of UUID string */ + args[0].Buffer.Pointer = pcie_uuid; + + /* arg1 - Revision ID */ + args[1].Type = ACPI_TYPE_INTEGER; + args[1].Integer.Value = PCIE_OSC_REVISION_ID; + + /* arg2 - Count */ + args[2].Type = ACPI_TYPE_INTEGER; + args[2].Integer.Value = 3; /* no. of DWORDS in caps_buffer */ + + /* arg3 - Capabilities Buffer */ + args[3].Type = ACPI_TYPE_BUFFER; + args[3].Buffer.Length = 12; + args[3].Buffer.Pointer = (void *)caps_buffer; + + /* Initialize Capabilities Buffer */ -/* - * Switch to native hot plug mode if possible. - */ -/*ARGSUSED*/ -static ACPI_STATUS -pciehpc_acpi_set_native_hp(dev_info_t *dip, ACPI_HANDLE osc_hdl) -{ - /* NOTE: This is currently not implemented */ - return (AE_ERROR); + /* DWORD1: no query flag set */ + caps_buffer[0] = 0; + /* DWORD2: Support Field */ + caps_buffer[1] = OSC_SUPPORT_FIELD_INIT; + /* DWORD3: Control Field */ + caps_buffer[2] = OSC_CONTROL_FIELD_INIT; + + rb.Length = ACPI_ALLOCATE_BUFFER; + rb.Pointer = NULL; + + status = AcpiEvaluateObject(osc_hdl, NULL, &arglist, &rb); + + if (status != AE_OK) { + PCIEHPC_DEBUG((CE_CONT, + "Failed to execute _OSC method (status %d)\n", status)); + return (status); + } + + rv = rb.Pointer; + ASSERT(rv->Type == ACPI_TYPE_BUFFER); + rbuf = (UINT32 *)rv->Buffer.Pointer; + + /* check the STATUS word in the capability buffer */ + if (rbuf[0] & OSC_STATUS_ERRORS) { + PCIEHPC_DEBUG((CE_CONT, "_OSC method failed (STATUS %d)\n", + rbuf[0])); + AcpiOsFree(rv); + return (AE_ERROR); + } + + PCIEHPC_DEBUG((CE_CONT, "_OSC method evaluation completed: " + "STATUS 0x%x SUPPORT 0x%x CONTROL 0x%x\n", + rbuf[0], rbuf[1], rbuf[2])); + + /* check if the Native Hot-Plug Control is granted */ + if (rbuf[2] & OSC_CONTROL_PCIE_NAT_HP) + *hp_mode = NATIVE_HP_MODE; + else + *hp_mode = ACPI_HP_MODE; + + AcpiOsFree(rv); + + return (AE_OK); } #ifdef DEBUG @@ -866,3 +930,26 @@ } } #endif + +static ACPI_STATUS +pciehpc_acpi_find_osc(ACPI_HANDLE busobj, ACPI_HANDLE *osc_hdlp) +{ + ACPI_HANDLE parentobj = busobj; + ACPI_STATUS status = AE_NOT_FOUND; + + *osc_hdlp = NULL; + + /* + * Walk up the ACPI device tree looking for _OSC method. + */ + do { + busobj = parentobj; + if ((status = AcpiGetHandle(busobj, "_OSC", osc_hdlp)) == AE_OK) + break; + } while (AcpiGetParent(busobj, &parentobj) == AE_OK); + + if (*osc_hdlp == NULL) + status = AE_NOT_FOUND; + + return (status); +}
--- a/usr/src/uts/intel/io/hotplug/pciehpc/pciehpc_acpi.h Mon Aug 27 14:04:30 2007 -0700 +++ b/usr/src/uts/intel/io/hotplug/pciehpc/pciehpc_acpi.h Mon Aug 27 14:40:46 2007 -0700 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -71,26 +70,41 @@ /* * _OSC method Capabilities buffer bit definitions (from PCI FW 3.0) */ -/* first DWORD: errors from _OSC invocation (except bit 0) */ -#define OSC_DWORD1_QUERY_ENABLE 0x1 /* Query Support Flag */ -#define OSC_DWORD1_FAILED 0x2 /* _OSC failure */ -#define OSC_DWORD1_INV_UUID 0x4 /* invalid UUID */ -#define OSC_DWORD1_INV_REVID 0x8 /* invalid revision ID */ -#define OSC_CAPS_MASKED 0x10 /* capabilities masked */ +/* first DWORD: status from _OSC invocation (except bit 0) */ +#define OSC_STATUS_QUERY_ENABLE 0x1 /* Query Support Flag */ +#define OSC_STATUS_FAILED 0x2 /* _OSC failure */ +#define OSC_STATUS_INV_UUID 0x4 /* invalid UUID */ +#define OSC_STATUS_INV_REVID 0x8 /* invalid revision ID */ +#define OSC_STATUS_CAPS_MASKED 0x10 /* capabilities masked */ + +#define OSC_STATUS_ERRORS \ + (OSC_STATUS_FAILED | OSC_STATUS_INV_UUID | OSC_STATUS_INV_REVID) /* second DWORD: Support Field (set by OS) */ -#define OSC_DWORD2_EXT_PCI_CFG 0x1 /* Extended PCI Config Ops supported */ -#define OSC_DWORD2_ACT_PM 0x2 /* Active State PM supported */ -#define OSC_DWORD2_CLK_PM_CAP 0x4 /* Clock PM Capability supported */ -#define OSC_DWORD2_PCI_SEGS 0x8 /* PCI Segment Groups supported */ -#define OSC_DWORD2_MSI 0x10 /* MSI supported */ +#define OSC_SUPPORT_EXT_PCI_CFG 0x1 /* Extended PCI Config Ops supported */ +#define OSC_SUPPORT_ACT_PM 0x2 /* Active State PM supported */ +#define OSC_SUPPORT_CLK_PM_CAP 0x4 /* Clock PM Capability supported */ +#define OSC_SUPPORT_PCI_SEGS 0x8 /* PCI Segment Groups supported */ +#define OSC_SUPPORT_MSI 0x10 /* MSI supported */ /* third DWORD: Control Field (set by OS/BIOS) */ -#define OSC_DWORD3_PCIE_NAT_HP 0x1 /* PCI Exp Native Hot Plug control */ -#define OSC_DWORD3_SHPC_NAT_HP 0x2 /* SHPC Native Hot Plug control */ -#define OSC_DWORD3_PCIE_NAT_PM 0x4 /* PCI Exp Native Power Mgmt. control */ -#define OSC_DWORD3_PCIE_ADV_ERR 0x8 /* PCIE Advanced Err. rep. control */ -#define OSC_DWORD3_PCE_CAPS 0x10 /* PCIE Caps Structure control */ +#define OSC_CONTROL_PCIE_NAT_HP 0x1 /* PCI Exp Native Hot Plug control */ +#define OSC_CONTROL_SHPC_NAT_HP 0x2 /* SHPC Native Hot Plug control */ +#define OSC_CONTROL_PCIE_NAT_PM 0x4 /* PCI Exp Native Power Mgmt. control */ +#define OSC_CONTROL_PCIE_ADV_ERR 0x8 /* PCIE Advanced Err. rep. control */ +#define OSC_CONTROL_PCIE_CAPS 0x10 /* PCIE Caps Structure control */ + +#define OSC_CONTROL_FIELD_INIT \ + (OSC_CONTROL_PCIE_NAT_PM | OSC_CONTROL_PCIE_NAT_HP | \ + OSC_CONTROL_PCIE_CAPS | OSC_CONTROL_PCIE_ADV_ERR) + +#define OSC_SUPPORT_FIELD_INIT \ + (OSC_SUPPORT_EXT_PCI_CFG | \ + OSC_SUPPORT_ACT_PM | OSC_SUPPORT_CLK_PM_CAP | \ + OSC_SUPPORT_MSI | OSC_SUPPORT_PCI_SEGS) + +#define ACPI_HP_MODE 1 +#define NATIVE_HP_MODE 2 /* Device status bit as returned by _STA method (see 6.3.7 of ACPI 3.0) */ #define DEV_STS_PRESENT 0x1 /* device is present */