ACPI based I/O APIC hot-plug
PATCH 3/3 ACPI based I/O APIC hot-plug
This patch adds PCI based I/O xAPIC hot-add support to ACPIPHP driver. When PCI root bridge is hot-added, all PCI based I/O xAPICs under the root bridge are hot-added by this patch. Hot-remove support is TBD.
---
linux-2.6.12-rc2-mm3-kanesige/drivers/pci/hotplug/acpiphp_glue.c | 120 ++++++++++ 1 files changed, 120 insertions(+)
drivers/pci/hotplug/acpiphp_glue.c renamed from drivers/pci/hotplug/acpiphp_glue.c~acpiphp_ioapic_add +120 -0
@@ -552,6 +552,125 @@ static void remove_bridge(acpi_handle ha } } +static struct pci_dev *get_apic_pci_info (acpi_handle handle) +{ +struct acpi_pci_id id; +struct pci_bus *bus; +struct pci_dev *dev; + +if (ACPI_FAILURE (acpi_get_pci_id (handle, &id))) +return NULL ; + + bus =pci_find_bus (id.segment, id.bus); +if (!bus) +return NULL ; + +list_for_each_entry (dev, &bus->devices, bus_list) { +if (dev->devfn !=PCI_DEVFN (id.device, id.function)) +continue ; +if ((dev->class >>8 ) !=PCI_CLASS_SYSTEM_PIC ) +continue ; +if ((dev->class &0xff ) ==0x10 || (dev->class &0xff ) ==0x20 ) +return dev; + } +return NULL ; +} + +static int get_gsi_base (acpi_handle handle,u32 *gsi_base) +{ +acpi_status status; +int result =-1 ; +unsigned 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 result; + + obj = buffer.pointer; +if (obj->type !=ACPI_TYPE_BUFFER ) + goto out; + + table = obj->buffer.pointer; +switch (((acpi_table_entry_header *)table)->type) { +case ACPI_MADT_IOSAPIC : + *gsi_base = ((struct acpi_table_iosapic *)table)->global_irq_base; + result =0 ; +break ; +case ACPI_MADT_IOAPIC : + *gsi_base = ((struct acpi_table_ioapic *)table)->global_irq_base; + result =0 ; +break ; +default : +break ; + } + out: +acpi_os_free (buffer.pointer); +return result; +} + +static acpi_status +ioapic_add (acpi_handle handle,u32 lvl,void *context,void **rv) +{ +acpi_status status; +unsigned long sta; +acpi_handle tmp; +struct pci_dev *pdev; +u32 gsi_base; +u64 phys_addr; + +/* 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 ; + + pdev =get_apic_pci_info (handle); +if (!pdev) +return AE_OK ; + +if (get_gsi_base (handle, &gsi_base)) +return AE_OK ; + +if (pci_enable_device (pdev)) +return AE_OK ; + +pci_set_master (pdev); + +if (pci_request_region (pdev,0 ,"I/O APIC(acpiphp)" )) { +pci_disable_device (pdev); +return AE_OK ; + } + + phys_addr =pci_resource_start (pdev,0 ); +if (acpi_register_ioapic (handle, phys_addr, gsi_base)) { +pci_release_region (pdev,0 ); +pci_disable_device (pdev); +return AE_OK ; + } + +return AE_OK ; +} + +static int acpiphp_configure_ioapics (acpi_handle handle) +{ +acpi_walk_namespace (ACPI_TYPE_DEVICE , handle, +ACPI_UINT32_MAX , ioapic_add,NULL ,NULL ); +return 0 ; +} +static int power_on_slot (struct acpiphp_slot *slot) {acpi_status status;
@@ -942,6 +1061,7 @@ static int acpiphp_configure_bridge (acpacpiphp_sanitize_bus (bus);acpiphp_set_hpp_values (handle, bus);pci_enable_bridges (bus); +acpiphp_configure_ioapics (handle);return 0 ; }
_
Quoted 1 line
+static struct
pci_dev*get_apic_pci_info(acpi_handle handle)
Nitpick: follow function declaration style of file.
Quoted 4 lines
drivers/pci/hotplug/acpiphp_glue.c renamed from drivers/pci/hotplug/acpiphp_glue.c~acpiphp_ioapic_add +4
-0+struct acpi_pci_id id; +struct pci_bus *bus; +struct pci_dev *dev; +
drivers/pci/hotplug/acpiphp_glue.c static void remove_bridge(acpi_handle ha · line 570
Quoted 10 lines
drivers/pci/hotplug/acpiphp_glue.c renamed from drivers/pci/hotplug/acpiphp_glue.c~acpiphp_ioapic_add +10
-0+if (ACPI_FAILURE (acpi_get_pci_id (handle, &id))) +return NULL ; + + bus =pci_find_bus (id.segment, id.bus); +if (!bus) +return NULL ; + +list_for_each_entry (dev, &bus->devices, bus_list) { +if (dev->devfn !=PCI_DEVFN (id.device, id.function)) +continue ;
Use pci_get_slot() here rather than walking bus->devices yourself.
drivers/pci/hotplug/acpiphp_glue.c static void remove_bridge(acpi_handle ha · line 573
Quoted 3 lines
drivers/pci/hotplug/acpiphp_glue.c renamed from drivers/pci/hotplug/acpiphp_glue.c~acpiphp_ioapic_add +3
-0+if ((dev->class >>8 ) !=PCI_CLASS_SYSTEM_PIC ) +continue ; +if ((dev->class &0xff ) ==0x10 || (dev->class &0xff ) ==0x20 )
What are 0x10 and 0x20? Looks like they should be #defines in include/linux/pci_ids.h.
Quoted 8 lines
drivers/pci/hotplug/acpiphp_glue.c renamed from drivers/pci/hotplug/acpiphp_glue.c~acpiphp_ioapic_add +8
-0+static int get_gsi_base (acpi_handle handle,u32 *gsi_base) +{ +acpi_status status; +int result =-1 ; +unsigned long gsb; +struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER ,NULL }; +union acpi_object *obj; +void *table;
drivers/pci/hotplug/acpiphp_glue.c static void remove_bridge(acpi_handle ha · line 596
Quoted 10 lines
drivers/pci/hotplug/acpiphp_glue.c renamed from drivers/pci/hotplug/acpiphp_glue.c~acpiphp_ioapic_add +10
-0+ + 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 result;
Nothing can modify result before this point, so it'd be clearer to just "return -1" here.
Quoted 8 lines · Bjorn Helgaas
drivers/pci/hotplug/acpiphp_glue.c static void remove_bridge(acpi_handle ha · line 573
Quoted 4 lines
drivers/pci/hotplug/acpiphp_glue.c renamed from drivers/pci/hotplug/acpiphp_glue.c~acpiphp_ioapic_add +3
-0+if ((dev->class >>8 ) !=PCI_CLASS_SYSTEM_PIC ) +continue ; +if ((dev->class &0xff ) ==0x10 || (dev->class &0xff ) ==0x20 )What are
0x10and0x20? Looks like they should be #defines ininclude/linux/pci_ids.h.
0x10 and 0x20 are programing interfaces for I/O APIC and I/O xAPIC respectively. #define for these values looks good. But I don't know if I can put new #defines into pci_ids.h and how to name them because I could not find the header file (including pci_ids.h) that #defines the values for programming interfaces. So I want to add the comments to explain these values (0x10, 0x20) instead of adding new #defines into pci_ids.h for now.
Thanks,
Kenji Kaneshige
Quoted 10 lines · Kenji Kaneshige
Quoted 8 lines · Bjorn Helgaas
drivers/pci/hotplug/acpiphp_glue.c static void remove_bridge(acpi_handle ha · line 573
Quoted 4 lines
drivers/pci/hotplug/acpiphp_glue.c renamed from drivers/pci/hotplug/acpiphp_glue.c~acpiphp_ioapic_add +3
-0+if ((dev->class >>8 ) !=PCI_CLASS_SYSTEM_PIC ) +continue ; +if ((dev->class &0xff ) ==0x10 || (dev->class &0xff ) ==0x20 )What are
0x10and0x20? Looks like they should be #defines ininclude/linux/pci_ids.h.
Quoted 7 lines
0x10and0x20are programing interfaces for I/O APIC and I/O xAPIC respectively. #define for these values looks good. But I don't know if I can put new #defines intopci_ids.hand how to name them because I could not find the header file (includingpci_ids.h) that #defines the values for programming interfaces. So I want to add the comments to explain these values (0x10,0x20) instead of adding new #defines intopci_ids.hfor now.
I think your patch should just add the values to pci_ids.h. If somebody doesn't like that, he or she will complain and you can fall back to just using 0x10 and 0x20. But I suspect it will be fine.
Quoted 19 lines · Bjorn Helgaas
Quoted 10 lines · Kenji Kaneshige
Quoted 8 lines · Bjorn Helgaas
drivers/pci/hotplug/acpiphp_glue.c static void remove_bridge(acpi_handle ha · line 573
Quoted 4 lines
drivers/pci/hotplug/acpiphp_glue.c renamed from drivers/pci/hotplug/acpiphp_glue.c~acpiphp_ioapic_add +3
-0+if ((dev->class >>8 ) !=PCI_CLASS_SYSTEM_PIC ) +continue ; +if ((dev->class &0xff ) ==0x10 || (dev->class &0xff ) ==0x20 )What are
0x10and0x20? Looks like they should be #defines ininclude/linux/pci_ids.h.Quoted 7 lines
0x10and0x20are programing interfaces for I/O APIC and I/O xAPIC respectively. #define for these values looks good. But I don't know if I can put new #defines intopci_ids.hand how to name them because I could not find the header file (includingpci_ids.h) that #defines the values for programming interfaces. So I want to add the comments to explain these values (0x10,0x20) instead of adding new #defines intopci_ids.hfor now.
Quoted 3 lines
I think your patch should just add the values to
pci_ids.h. If somebody doesn't like that, he or she will complain and you can fall back to just using0x10and0x20. But I suspect it will be fine.
Yes, I have no problem with that.
thanks,
greg k-h
-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users. Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click
Quoted 21 lines · Bjorn Helgaas
Quoted 10 lines · Kenji Kaneshige
Quoted 7 lines · Bjorn Helgaas
drivers/pci/hotplug/acpiphp_glue.c static void remove_bridge(acpi_handle ha · line 573
Quoted 3 lines
drivers/pci/hotplug/acpiphp_glue.c renamed from drivers/pci/hotplug/acpiphp_glue.c~acpiphp_ioapic_add +3
-0+if ((dev->class >>8 ) !=PCI_CLASS_SYSTEM_PIC ) +continue ; +if ((dev->class &0xff ) ==0x10 || (dev->class &0xff ) ==0x20 )What are
0x10and0x20? Looks like they should be #defines ininclude/linux/pci_ids.h.Quoted 7 lines
0x10and0x20are programing interfaces for I/O APIC and I/O xAPIC respectively. #define for these values looks good. But I don't know if I can put new #defines intopci_ids.hand how to name them because I could not find the header file (includingpci_ids.h) that #defines the values for programming interfaces. So I want to add the comments to explain these values (0x10,0x20) instead of adding new #defines intopci_ids.hfor now.
Quoted 5 lines
I think your patch should just add the values to
pci_ids.h. If somebody doesn't like that, he or she will complain and you can fall back to just using0x10and0x20. But I suspect it will be fine.
Thank you for advice. I'll try to add new #defines for I/O APIC and I/O xAPIC to pci_ids.h.
Thanks,
Kenji Kaneshige