2 * IOAPIC/IOxAPIC/IOSAPIC driver
4 * Copyright (C) 2009 Fujitsu Limited.
5 * (c) Copyright 2009 Hewlett-Packard Development Company, L.P.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
13 * This driver manages PCI I/O APICs added by hotplug after boot. We try to
14 * claim all I/O APIC PCI devices, but those present at boot were registered
15 * when we parsed the ACPI MADT, so we'll fail when we try to re-register
19 #include <linux/pci.h>
20 #include <linux/acpi.h>
21 #include <acpi/acpi_bus.h>
28 static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
32 unsigned long long gsb;
33 struct ioapic *ioapic;
38 handle = DEVICE_ACPI_HANDLE(&dev->dev);
42 status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);
43 if (ACPI_FAILURE(status))
47 * The previous code in acpiphp evaluated _MAT if _GSB failed, but
48 * ACPI spec 4.0 sec 6.2.2 requires _GSB for hot-pluggable I/O APICs.
51 ioapic = kzalloc(sizeof(*ioapic), GFP_KERNEL);
55 ioapic->handle = handle;
56 ioapic->gsi_base = (u32) gsb;
58 if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC)
63 ret = pci_enable_device(dev);
69 if (pci_request_region(dev, 0, type))
72 addr = pci_resource_start(dev, 0);
73 if (acpi_register_ioapic(ioapic->handle, addr, ioapic->gsi_base))
76 pci_set_drvdata(dev, ioapic);
77 dev_info(&dev->dev, "%s at %#llx, GSI %u\n", type, addr,
82 pci_release_region(dev, 0);
84 pci_disable_device(dev);
90 static void ioapic_remove(struct pci_dev *dev)
92 struct ioapic *ioapic = pci_get_drvdata(dev);
94 acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base);
95 pci_release_region(dev, 0);
96 pci_disable_device(dev);
101 static struct pci_device_id ioapic_devices[] = {
102 { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
103 PCI_CLASS_SYSTEM_PIC_IOAPIC << 8, 0xffff00, },
104 { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
105 PCI_CLASS_SYSTEM_PIC_IOXAPIC << 8, 0xffff00, },
109 static struct pci_driver ioapic_driver = {
111 .id_table = ioapic_devices,
112 .probe = ioapic_probe,
113 .remove = __devexit_p(ioapic_remove),
116 static int __init ioapic_init(void)
118 return pci_register_driver(&ioapic_driver);
121 static void __exit ioapic_exit(void)
123 pci_unregister_driver(&ioapic_driver);
126 module_init(ioapic_init);
127 module_exit(ioapic_exit);