Commit 5db66334 authored by Jiang Liu's avatar Jiang Liu Committed by Thomas Gleixner

PCI: Remove PCI ioapic driver

To support IOAPIC hotplug on x86 and IA64 platforms, OS needs to figure
out global interrupt source number(GSI) and IOAPIC enumeration ID
through ACPI interfaces. So BIOS must implement an ACPI IOAPIC device
with _GSB/_UID or _MAT method to support IOAPIC hotplug. OS also needs
to figure out base physical address to access IOAPIC registers. OS may
get the base physical address through PCI BARs if IOAPIC device is
visible in PCI domain, otherwise OS may get the address by ACPI _CRS
method if IOAPIC device is hidden from PCI domain by BIOS.

When adding a PCI subtree, we need to add IOAPIC devices before enabling
all other PCI devices because other PCI devices may use the IOAPIC to
allocate PCI interrupts.

So we plan to reimplement IOAPIC driver as an ACPI instead of PCI driver
due to:
1) hot-pluggable IOAPIC devices are always visible in ACPI domain,
   but may or may not be visible in PCI domain.
2) we could explicitly control the order between IOAPIC and other PCI
   devices.

We also have another choice to use a PCI driver to manage IOAPIC device
if it's visible in PCI domain and use an ACPI driver if it's only
visible in ACPI domain. But this solution is a little complex.

It shouldn't cause serious backward compatibility issues because:
1) IOAPIC hotplug is never supported on x86 yet because it hasn't
   implemented the required acpi_register_ioapic() and
   acpi_unregister_ioapic().
2) Currently only ACPI based IOAPIC hotplug is possible on x86 and
   IA64, we don't know other specifications and interfaces to support
   IOAPIC hotplug yet.
3) We will reimplement an ACPI IOAPIC driver to support IOAPIC hotplug.

This change also helps to get rid of the false alarm on all current
Linux distributions:
[    6.952497] ioapic: probe of 0000:00:05.4 failed with error -22
[    6.959542] ioapic: probe of 0000:80:05.4 failed with error -22
Signed-off-by: default avatarJiang Liu <jiang.liu@linux.intel.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Link: http://lkml.kernel.org/r/1414387308-27148-9-git-send-email-jiang.liu@linux.intel.comSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 2414e021
......@@ -110,13 +110,6 @@ config PCI_PASID
If unsure, say N.
config PCI_IOAPIC
bool "PCI IO-APIC hotplug support" if X86
depends on PCI
depends on ACPI
depends on X86_IO_APIC
default !X86
config PCI_LABEL
def_bool y if (DMI || ACPI)
select NLS
......
......@@ -13,8 +13,6 @@ obj-$(CONFIG_PCI_QUIRKS) += quirks.o
# Build PCI Express stuff if needed
obj-$(CONFIG_PCIEPORTBUS) += pcie/
obj-$(CONFIG_PCI_IOAPIC) += ioapic.o
# Build the PCI Hotplug drivers if we were asked to
obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
ifdef CONFIG_HOTPLUG_PCI
......
/*
* IOAPIC/IOxAPIC/IOSAPIC driver
*
* Copyright (C) 2009 Fujitsu Limited.
* (c) Copyright 2009 Hewlett-Packard Development Company, L.P.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*
* This driver manages PCI I/O APICs added by hotplug after boot. We try to
* claim all I/O APIC PCI devices, but those present at boot were registered
* when we parsed the ACPI MADT, so we'll fail when we try to re-register
* them.
*/
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/acpi.h>
#include <linux/slab.h>
struct ioapic {
acpi_handle handle;
u32 gsi_base;
};
static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
{
acpi_handle handle;
acpi_status status;
unsigned long long gsb;
struct ioapic *ioapic;
int ret;
char *type;
struct resource *res;
handle = ACPI_HANDLE(&dev->dev);
if (!handle)
return -EINVAL;
status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);
if (ACPI_FAILURE(status))
return -EINVAL;
/*
* The previous code in acpiphp evaluated _MAT if _GSB failed, but
* ACPI spec 4.0 sec 6.2.2 requires _GSB for hot-pluggable I/O APICs.
*/
ioapic = kzalloc(sizeof(*ioapic), GFP_KERNEL);
if (!ioapic)
return -ENOMEM;
ioapic->handle = handle;
ioapic->gsi_base = (u32) gsb;
if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC)
type = "IOAPIC";
else
type = "IOxAPIC";
ret = pci_enable_device(dev);
if (ret < 0)
goto exit_free;
pci_set_master(dev);
if (pci_request_region(dev, 0, type))
goto exit_disable;
res = &dev->resource[0];
if (acpi_register_ioapic(ioapic->handle, res->start, ioapic->gsi_base))
goto exit_release;
pci_set_drvdata(dev, ioapic);
dev_info(&dev->dev, "%s at %pR, GSI %u\n", type, res, ioapic->gsi_base);
return 0;
exit_release:
pci_release_region(dev, 0);
exit_disable:
pci_disable_device(dev);
exit_free:
kfree(ioapic);
return -ENODEV;
}
static void ioapic_remove(struct pci_dev *dev)
{
struct ioapic *ioapic = pci_get_drvdata(dev);
acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base);
pci_release_region(dev, 0);
pci_disable_device(dev);
kfree(ioapic);
}
static const struct pci_device_id ioapic_devices[] = {
{ PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOAPIC, ~0) },
{ PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOXAPIC, ~0) },
{ }
};
MODULE_DEVICE_TABLE(pci, ioapic_devices);
static struct pci_driver ioapic_driver = {
.name = "ioapic",
.id_table = ioapic_devices,
.probe = ioapic_probe,
.remove = ioapic_remove,
};
static int __init ioapic_init(void)
{
return pci_register_driver(&ioapic_driver);
}
module_init(ioapic_init);
MODULE_LICENSE("GPL");
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