Commit 3d3c5375 authored by Takayoshi Kochi's avatar Takayoshi Kochi Committed by Greg Kroah-Hartman

[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
parent 19952652
...@@ -235,7 +235,7 @@ extern u32 acpiphp_get_address (struct acpiphp_slot *slot); ...@@ -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 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_slot (struct acpiphp_slot *slot);
extern int acpiphp_configure_function (struct acpiphp_func *func); 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_detect_pci_resource (struct acpiphp_bridge *bridge);
extern int acpiphp_init_func_resource (struct acpiphp_func *func); extern int acpiphp_init_func_resource (struct acpiphp_func *func);
......
...@@ -694,14 +694,14 @@ static int power_on_slot(struct acpiphp_slot *slot) ...@@ -694,14 +694,14 @@ static int power_on_slot(struct acpiphp_slot *slot)
func = list_entry(l, struct acpiphp_func, sibling); func = list_entry(l, struct acpiphp_func, sibling);
if (func->flags & FUNC_HAS_PS0) { if (func->flags & FUNC_HAS_PS0) {
dbg("%s: executing _PS0 on %s\n", __FUNCTION__, dbg("%s: executing _PS0\n", __FUNCTION__);
pci_name(func->pci_dev));
status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL); status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
warn("%s: _PS0 failed\n", __FUNCTION__); warn("%s: _PS0 failed\n", __FUNCTION__);
retval = -1; retval = -1;
goto err_exit; goto err_exit;
} } else
break;
} }
} }
...@@ -737,7 +737,8 @@ static int power_off_slot(struct acpiphp_slot *slot) ...@@ -737,7 +737,8 @@ static int power_off_slot(struct acpiphp_slot *slot)
warn("%s: _PS3 failed\n", __FUNCTION__); warn("%s: _PS3 failed\n", __FUNCTION__);
retval = -1; retval = -1;
goto err_exit; goto err_exit;
} } else
break;
} }
} }
...@@ -757,7 +758,8 @@ static int power_off_slot(struct acpiphp_slot *slot) ...@@ -757,7 +758,8 @@ static int power_off_slot(struct acpiphp_slot *slot)
warn("%s: _EJ0 failed\n", __FUNCTION__); warn("%s: _EJ0 failed\n", __FUNCTION__);
retval = -1; retval = -1;
goto err_exit; goto err_exit;
} } else
break;
} }
} }
...@@ -865,15 +867,8 @@ static int disable_device(struct acpiphp_slot *slot) ...@@ -865,15 +867,8 @@ static int disable_device(struct acpiphp_slot *slot)
list_for_each (l, &slot->funcs) { list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling); func = list_entry(l, struct acpiphp_func, sibling);
if (func->pci_dev) { if (func->pci_dev)
if (acpiphp_unconfigure_function(func) == 0) { acpiphp_unconfigure_function(func);
func->pci_dev = NULL;
} else {
err("failed to unconfigure device\n");
retval = -1;
goto err_exit;
}
}
} }
slot->flags &= (~SLOT_ENABLED); slot->flags &= (~SLOT_ENABLED);
...@@ -1269,7 +1264,7 @@ int acpiphp_check_bridge(struct acpiphp_bridge *bridge) ...@@ -1269,7 +1264,7 @@ int acpiphp_check_bridge(struct acpiphp_bridge *bridge)
up(&slot->crit_sect); up(&slot->crit_sect);
goto err_exit; goto err_exit;
} }
enabled++; disabled++;
} }
} else { } else {
/* if disabled but present, enable */ /* if disabled but present, enable */
...@@ -1280,7 +1275,7 @@ int acpiphp_check_bridge(struct acpiphp_bridge *bridge) ...@@ -1280,7 +1275,7 @@ int acpiphp_check_bridge(struct acpiphp_bridge *bridge)
up(&slot->crit_sect); up(&slot->crit_sect);
goto err_exit; goto err_exit;
} }
disabled++; enabled++;
} }
} }
} }
......
...@@ -83,8 +83,8 @@ static int init_config_space (struct acpiphp_func *func) ...@@ -83,8 +83,8 @@ static int init_config_space (struct acpiphp_func *func)
if (bar & PCI_BASE_ADDRESS_SPACE_IO) { if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
/* This is IO */ /* This is IO */
len = bar & 0xFFFFFFFC; len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
len = ~len + 1; len = len & ~(len - 1);
dbg("len in IO %x, BAR %d\n", len, count); 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 * ...@@ -226,8 +226,8 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *
if (len & PCI_BASE_ADDRESS_SPACE_IO) { if (len & PCI_BASE_ADDRESS_SPACE_IO) {
/* This is IO */ /* This is IO */
base = bar & 0xFFFFFFFC; base = bar & 0xFFFFFFFC;
len &= 0xFFFFFFFC; len = len & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
len = ~len + 1; len = len & ~(len - 1);
dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + 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) ...@@ -351,8 +351,8 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
if (len & PCI_BASE_ADDRESS_SPACE_IO) { if (len & PCI_BASE_ADDRESS_SPACE_IO) {
/* This is IO */ /* This is IO */
base = bar & 0xFFFFFFFC; base = bar & 0xFFFFFFFC;
len &= 0xFFFFFFFC; len = len & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
len = ~len + 1; len = len & ~(len - 1);
dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + 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) ...@@ -485,14 +485,14 @@ int acpiphp_configure_function (struct acpiphp_func *func)
* @func: function to be unconfigured * @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; struct acpiphp_bridge *bridge;
int retval = 0; int retval = 0;
/* if pci_dev is NULL, ignore it */ /* if pci_dev is NULL, ignore it */
if (!func->pci_dev) if (!func->pci_dev)
goto err_exit; return;
pci_remove_bus_device(func->pci_dev); pci_remove_bus_device(func->pci_dev);
...@@ -505,7 +505,4 @@ int acpiphp_unconfigure_function (struct acpiphp_func *func) ...@@ -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->p_mem_head, &bridge->p_mem_head);
acpiphp_move_resource(&func->bus_head, &bridge->bus_head); acpiphp_move_resource(&func->bus_head, &bridge->bus_head);
spin_unlock(&bridge->res_lock); spin_unlock(&bridge->res_lock);
err_exit:
return retval;
} }
...@@ -224,7 +224,7 @@ struct pci_resource *acpiphp_get_io_resource (struct pci_resource **head, u32 si ...@@ -224,7 +224,7 @@ struct pci_resource *acpiphp_get_io_resource (struct pci_resource **head, u32 si
} /* End of too big on top end */ } /* End of too big on top end */
/* For IO make sure it's not in the ISA aliasing space */ /* For IO make sure it's not in the ISA aliasing space */
if (node->base & 0x300L) if ((node->base & 0x300L) && !(node->base & 0xfffff000))
continue; continue;
/* If we got here, then it is the right size /* If we got here, then it is the right size
......
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