diff options
author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2009-10-26 11:20:47 -0600 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-11-04 13:06:39 -0800 |
commit | 204d49a5613a06eb2fa5c3b842a29b1336cc7995 (patch) | |
tree | 942a75a2a900858c7bd34af0669256e09faae577 /drivers/pci/hotplug/acpiphp_glue.c | |
parent | 476f644edf7c22b47e6a118e4a1e138112a5ef14 (diff) | |
download | op-kernel-dev-204d49a5613a06eb2fa5c3b842a29b1336cc7995.zip op-kernel-dev-204d49a5613a06eb2fa5c3b842a29b1336cc7995.tar.gz |
PCI hotplug: move IOAPIC support from acpiphp to ioapic driver
This patch moves PCI I/O APIC support from acpiphp to a separate driver.
Like pciehp and shpchp, acpiphp handles PCI hotplug, i.e., addition and
removal of PCI adapters. But in addition, acpiphp handles some ACPI
hotplug, such as the addition of new host bridges, and the I/O APIC
support was tangled up with that.
I don't think the I/O APIC support needs to be in acpiphp; PCI I/O APICs
usually appear as a function on a PCI host bridge, and we'll enumerate the
APIC before any of the devices behind the bridge that use it.
As far as I know, nobody actually uses I/O APIC hotplug. It depends on
acpi_register_ioapic(), which is only implemented for ia64, and I don't
think any vendors have supported I/O chassis hotplug yet.
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Reviewed-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
CC: Satoru Takeuchi <takeuchi_satoru@jp.fujitsu.com>
CC: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/hotplug/acpiphp_glue.c')
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 190 |
1 files changed, 0 insertions, 190 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 58d25a1..392e4b3 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -52,8 +52,6 @@ #include "acpiphp.h" static LIST_HEAD(bridge_list); -static LIST_HEAD(ioapic_list); -static DEFINE_SPINLOCK(ioapic_list_lock); #define MY_NAME "acpiphp_glue" @@ -606,190 +604,6 @@ static void remove_bridge(acpi_handle handle) handle_hotplug_event_bridge); } -static struct pci_dev * get_apic_pci_info(acpi_handle handle) -{ - struct pci_dev *dev; - - dev = acpi_get_pci_dev(handle); - if (!dev) - return NULL; - - if ((dev->class != PCI_CLASS_SYSTEM_PIC_IOAPIC) && - (dev->class != PCI_CLASS_SYSTEM_PIC_IOXAPIC)) - { - pci_dev_put(dev); - return NULL; - } - - return dev; -} - -static int get_gsi_base(acpi_handle handle, u32 *gsi_base) -{ - acpi_status status; - int result = -1; - unsigned long long gsb; - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - union acpi_object *obj; - void *table; - - status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb); - if (ACPI_SUCCESS(status)) { - *gsi_base = (u32)gsb; - return 0; - } - - status = acpi_evaluate_object(handle, "_MAT", NULL, &buffer); - if (ACPI_FAILURE(status) || !buffer.length || !buffer.pointer) - return -1; - - obj = buffer.pointer; - if (obj->type != ACPI_TYPE_BUFFER) - goto out; - - table = obj->buffer.pointer; - switch (((struct acpi_subtable_header *)table)->type) { - case ACPI_MADT_TYPE_IO_SAPIC: - *gsi_base = ((struct acpi_madt_io_sapic *)table)->global_irq_base; - result = 0; - break; - case ACPI_MADT_TYPE_IO_APIC: - *gsi_base = ((struct acpi_madt_io_apic *)table)->global_irq_base; - result = 0; - break; - default: - break; - } - out: - kfree(buffer.pointer); - return result; -} - -static acpi_status -ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - acpi_status status; - unsigned long long sta; - acpi_handle tmp; - struct pci_dev *pdev; - u32 gsi_base; - u64 phys_addr; - struct acpiphp_ioapic *ioapic; - - /* Evaluate _STA if present */ - status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); - if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL) - return AE_CTRL_DEPTH; - - /* Scan only PCI bus scope */ - status = acpi_get_handle(handle, "_HID", &tmp); - if (ACPI_SUCCESS(status)) - return AE_CTRL_DEPTH; - - if (get_gsi_base(handle, &gsi_base)) - return AE_OK; - - ioapic = kmalloc(sizeof(*ioapic), GFP_KERNEL); - if (!ioapic) - return AE_NO_MEMORY; - - pdev = get_apic_pci_info(handle); - if (!pdev) - goto exit_kfree; - - if (pci_enable_device(pdev)) - goto exit_pci_dev_put; - - pci_set_master(pdev); - - if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)")) - goto exit_pci_disable_device; - - phys_addr = pci_resource_start(pdev, 0); - if (acpi_register_ioapic(handle, phys_addr, gsi_base)) - goto exit_pci_release_region; - - ioapic->gsi_base = gsi_base; - ioapic->dev = pdev; - spin_lock(&ioapic_list_lock); - list_add_tail(&ioapic->list, &ioapic_list); - spin_unlock(&ioapic_list_lock); - - return AE_OK; - - exit_pci_release_region: - pci_release_region(pdev, 0); - exit_pci_disable_device: - pci_disable_device(pdev); - exit_pci_dev_put: - pci_dev_put(pdev); - exit_kfree: - kfree(ioapic); - - return AE_OK; -} - -static acpi_status -ioapic_remove(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - acpi_status status; - unsigned long long sta; - acpi_handle tmp; - u32 gsi_base; - struct acpiphp_ioapic *pos, *n, *ioapic = NULL; - - /* Evaluate _STA if present */ - status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); - if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL) - return AE_CTRL_DEPTH; - - /* Scan only PCI bus scope */ - status = acpi_get_handle(handle, "_HID", &tmp); - if (ACPI_SUCCESS(status)) - return AE_CTRL_DEPTH; - - if (get_gsi_base(handle, &gsi_base)) - return AE_OK; - - acpi_unregister_ioapic(handle, gsi_base); - - spin_lock(&ioapic_list_lock); - list_for_each_entry_safe(pos, n, &ioapic_list, list) { - if (pos->gsi_base != gsi_base) - continue; - ioapic = pos; - list_del(&ioapic->list); - break; - } - spin_unlock(&ioapic_list_lock); - - if (!ioapic) - return AE_OK; - - pci_release_region(ioapic->dev, 0); - pci_disable_device(ioapic->dev); - pci_dev_put(ioapic->dev); - kfree(ioapic); - - return AE_OK; -} - -static int acpiphp_configure_ioapics(acpi_handle handle) -{ - ioapic_add(handle, 0, NULL, NULL); - acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, - ACPI_UINT32_MAX, ioapic_add, NULL, NULL); - return 0; -} - -static int acpiphp_unconfigure_ioapics(acpi_handle handle) -{ - ioapic_remove(handle, 0, NULL, NULL); - acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, - ACPI_UINT32_MAX, ioapic_remove, NULL, NULL); - return 0; -} - static int power_on_slot(struct acpiphp_slot *slot) { acpi_status status; @@ -1014,8 +828,6 @@ static int __ref enable_device(struct acpiphp_slot *slot) pci_bus_assign_resources(bus); acpiphp_sanitize_bus(bus); acpiphp_set_hpp_values(bus); - list_for_each_entry(func, &slot->funcs, sibling) - acpiphp_configure_ioapics(func->handle); pci_enable_bridges(bus); pci_bus_add_devices(bus); @@ -1091,7 +903,6 @@ static int disable_device(struct acpiphp_slot *slot) } list_for_each_entry(func, &slot->funcs, sibling) { - acpiphp_unconfigure_ioapics(func->handle); acpiphp_bus_trim(func->handle); } @@ -1275,7 +1086,6 @@ static int acpiphp_configure_bridge (acpi_handle handle) acpiphp_sanitize_bus(bus); acpiphp_set_hpp_values(bus); pci_enable_bridges(bus); - acpiphp_configure_ioapics(handle); return 0; } |