#include <linux/init.h>
#include <linux/acpi.h>
#include <linux/efi.h>
+#include <linux/pci-acpi.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#ifdef CONFIG_IA64
static void acpi_get__hpp ( struct acpi_bridge *ab);
static void acpi_run_oshp ( struct acpi_bridge *ab);
+static int osc_exist = 0;
+static int oshp_exist = 0;
+static int run__osc_success = 0;
+static int run_oshp_success = 0;
static int acpi_add_slot_to_php_slots(
struct acpi_bridge *ab,
ab->scanned += 1;
if (!ab->_hpp)
acpi_get__hpp(ab);
-
- acpi_run_oshp(ab);
+
+ if (!osc_exist)
+ acpi_run_oshp(ab);
if (sun != samesun) {
info("acpi_pciehprm: Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n",
}
ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL);
+ if (!ab->_hpp) {
+ err ("acpi_pciehprm:%s alloc for _HPP failed\n", path_name);
+ goto free_and_return;
+ }
memset(ab->_hpp, 0, sizeof(struct acpi__hpp));
ab->_hpp->cache_line_size = nui[0];
status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, &ret_buf);
if (ACPI_FAILURE(status)) {
err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status);
- } else
+ oshp_exist = (status == 0x5) ? 0 : 1;
+ } else {
+ oshp_exist = 1;
+ run_oshp_success = 1;
dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status);
+ }
return;
}
kfree(ab);
return NULL;
}
+ status = pci_osc_control_set (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
+ if (ACPI_FAILURE(status)) {
+ dbg("%s: status %x\n", __FUNCTION__, status);
+ } else {
+ run__osc_success = 1;
+ osc_exist = 1;
+ }
+ dbg("%s: status %x run__osc_success %x osc_exist %x \n",
+ __FUNCTION__, status, run__osc_success, osc_exist);
+
build_a_bridge(ab, ab);
return ab;
if (rc)
return rc;
+ if (!osc_exist) {
+ if (!oshp_exist) {
+ err("Both _OSC and OSHP methods do not exist\n");
+ rc = -ENODEV;
+ } else if (!run_oshp_success) {
+ err("Fails to run OSHP to gain control of native hot-plug\n");
+ rc = -ENODEV;
+ }
+ } else if (!run__osc_success) {
+ err("Fails to run _OSC to gain control of native hot-plug\n");
+ rc = -ENODEV;
+ }
+ dbg("%s: run__osc_success %x osc_exist %x\n", __FUNCTION__,
+ run__osc_success, osc_exist);
+ dbg("%s: run_oshp_success %x oshp_exist %x", __FUNCTION__,
+ run_oshp_success, oshp_exist);
+
dbg("pciehprm ACPI init %s\n", (rc)?"fail":"success");
return rc;
}
static int bind_pci_resources_to_slots ( struct controller *ctrl)
{
- struct pci_func *func;
+ struct pci_func *func, new_func;
int busn = ctrl->slot_bus;
int devn, funn;
u32 vid;
if (vid != 0xFFFFFFFF) {
dbg("%s: vid = %x\n", __FUNCTION__, vid);
func = pciehp_slot_find(busn, devn, funn);
- if (!func)
- continue;
- configure_existing_function(ctrl, func);
+ if (!func) {
+ memset(&new_func, 0, sizeof(struct pci_func));
+ new_func.bus = busn;
+ new_func.device = devn;
+ new_func.function = funn;
+ new_func.is_a_board = 1;
+ configure_existing_function(ctrl, &new_func);
+ pciehprm_dump_func_res(&new_func);
+ } else {
+ configure_existing_function(ctrl, func);
+ pciehprm_dump_func_res(func);
+ }
dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
- pciehprm_dump_func_res(func);
}
}
}