From 3d3c5375323b80fbd85f7c27949b6ffabaa8dc0e Mon Sep 17 00:00:00 2001 From: Takayoshi Kochi Date: Tue, 9 Mar 2004 22:22:59 -0800 Subject: [PATCH] [PATCH] PCI Hotlug: fix acpiphp unable to power off slots Attached patch includes the I/O space fix and applies to 2.6.3. This should also solve the problem Maeda-san reported in January (sorry for replying so late!) Here are changes in the patch: - fix the acpiphp driver not powering down a PCI card (from Gary Hade) - fix I/O space size calculation and ISA aliasing (from Gary Hade) - fix some debug messages - only execute ACPI methods on the first existing function --- drivers/pci/hotplug/acpiphp.h | 2 +- drivers/pci/hotplug/acpiphp_glue.c | 27 +++++++++++---------------- drivers/pci/hotplug/acpiphp_pci.c | 19 ++++++++----------- drivers/pci/hotplug/acpiphp_res.c | 2 +- 4 files changed, 21 insertions(+), 29 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 6d25ebf99fd50..cffa9f2ca5778 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -235,7 +235,7 @@ extern u32 acpiphp_get_address (struct acpiphp_slot *slot); extern struct pci_dev *acpiphp_allocate_pcidev (struct pci_bus *pbus, int dev, int fn); extern int acpiphp_configure_slot (struct acpiphp_slot *slot); extern int acpiphp_configure_function (struct acpiphp_func *func); -extern int acpiphp_unconfigure_function (struct acpiphp_func *func); +extern void acpiphp_unconfigure_function (struct acpiphp_func *func); extern int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge); extern int acpiphp_init_func_resource (struct acpiphp_func *func); diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 225b8c3f362bc..628fb25cca603 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -694,14 +694,14 @@ static int power_on_slot(struct acpiphp_slot *slot) func = list_entry(l, struct acpiphp_func, sibling); if (func->flags & FUNC_HAS_PS0) { - dbg("%s: executing _PS0 on %s\n", __FUNCTION__, - pci_name(func->pci_dev)); + dbg("%s: executing _PS0\n", __FUNCTION__); status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL); if (ACPI_FAILURE(status)) { warn("%s: _PS0 failed\n", __FUNCTION__); retval = -1; goto err_exit; - } + } else + break; } } @@ -737,7 +737,8 @@ static int power_off_slot(struct acpiphp_slot *slot) warn("%s: _PS3 failed\n", __FUNCTION__); retval = -1; goto err_exit; - } + } else + break; } } @@ -757,7 +758,8 @@ static int power_off_slot(struct acpiphp_slot *slot) warn("%s: _EJ0 failed\n", __FUNCTION__); retval = -1; goto err_exit; - } + } else + break; } } @@ -865,15 +867,8 @@ static int disable_device(struct acpiphp_slot *slot) list_for_each (l, &slot->funcs) { func = list_entry(l, struct acpiphp_func, sibling); - if (func->pci_dev) { - if (acpiphp_unconfigure_function(func) == 0) { - func->pci_dev = NULL; - } else { - err("failed to unconfigure device\n"); - retval = -1; - goto err_exit; - } - } + if (func->pci_dev) + acpiphp_unconfigure_function(func); } slot->flags &= (~SLOT_ENABLED); @@ -1269,7 +1264,7 @@ int acpiphp_check_bridge(struct acpiphp_bridge *bridge) up(&slot->crit_sect); goto err_exit; } - enabled++; + disabled++; } } else { /* if disabled but present, enable */ @@ -1280,7 +1275,7 @@ int acpiphp_check_bridge(struct acpiphp_bridge *bridge) up(&slot->crit_sect); goto err_exit; } - disabled++; + enabled++; } } } diff --git a/drivers/pci/hotplug/acpiphp_pci.c b/drivers/pci/hotplug/acpiphp_pci.c index 9d9dabdcee9c4..b1a338ba7bd47 100644 --- a/drivers/pci/hotplug/acpiphp_pci.c +++ b/drivers/pci/hotplug/acpiphp_pci.c @@ -83,8 +83,8 @@ static int init_config_space (struct acpiphp_func *func) if (bar & PCI_BASE_ADDRESS_SPACE_IO) { /* This is IO */ - len = bar & 0xFFFFFFFC; - len = ~len + 1; + len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF); + len = len & ~(len - 1); dbg("len in IO %x, BAR %d\n", len, count); @@ -226,8 +226,8 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev * if (len & PCI_BASE_ADDRESS_SPACE_IO) { /* This is IO */ base = bar & 0xFFFFFFFC; - len &= 0xFFFFFFFC; - len = ~len + 1; + len = len & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF); + len = len & ~(len - 1); dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1); @@ -351,8 +351,8 @@ int acpiphp_init_func_resource (struct acpiphp_func *func) if (len & PCI_BASE_ADDRESS_SPACE_IO) { /* This is IO */ base = bar & 0xFFFFFFFC; - len &= 0xFFFFFFFC; - len = ~len + 1; + len = len & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF); + len = len & ~(len - 1); dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1); @@ -485,14 +485,14 @@ int acpiphp_configure_function (struct acpiphp_func *func) * @func: function to be unconfigured * */ -int acpiphp_unconfigure_function (struct acpiphp_func *func) +void acpiphp_unconfigure_function (struct acpiphp_func *func) { struct acpiphp_bridge *bridge; int retval = 0; /* if pci_dev is NULL, ignore it */ if (!func->pci_dev) - goto err_exit; + return; pci_remove_bus_device(func->pci_dev); @@ -505,7 +505,4 @@ int acpiphp_unconfigure_function (struct acpiphp_func *func) acpiphp_move_resource(&func->p_mem_head, &bridge->p_mem_head); acpiphp_move_resource(&func->bus_head, &bridge->bus_head); spin_unlock(&bridge->res_lock); - - err_exit: - return retval; } diff --git a/drivers/pci/hotplug/acpiphp_res.c b/drivers/pci/hotplug/acpiphp_res.c index ba9cbb995030a..876c7bdd29ee8 100644 --- a/drivers/pci/hotplug/acpiphp_res.c +++ b/drivers/pci/hotplug/acpiphp_res.c @@ -224,7 +224,7 @@ struct pci_resource *acpiphp_get_io_resource (struct pci_resource **head, u32 si } /* End of too big on top end */ /* For IO make sure it's not in the ISA aliasing space */ - if (node->base & 0x300L) + if ((node->base & 0x300L) && !(node->base & 0xfffff000)) continue; /* If we got here, then it is the right size -- 2.53.0