• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/pci/
1/*
2 * IOAPIC/IOxAPIC/IOSAPIC driver
3 *
4 * Copyright (C) 2009 Fujitsu Limited.
5 * (c) Copyright 2009 Hewlett-Packard Development Company, L.P.
6 *
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.
10 */
11
12/*
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
16 * them.
17 */
18
19#include <linux/pci.h>
20#include <linux/acpi.h>
21#include <linux/slab.h>
22#include <acpi/acpi_bus.h>
23
24struct ioapic {
25	acpi_handle	handle;
26	u32		gsi_base;
27};
28
29static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
30{
31	acpi_handle handle;
32	acpi_status status;
33	unsigned long long gsb;
34	struct ioapic *ioapic;
35	int ret;
36	char *type;
37	struct resource *res;
38
39	handle = DEVICE_ACPI_HANDLE(&dev->dev);
40	if (!handle)
41		return -EINVAL;
42
43	status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);
44	if (ACPI_FAILURE(status))
45		return -EINVAL;
46
47	/*
48	 * The previous code in acpiphp evaluated _MAT if _GSB failed, but
49	 * ACPI spec 4.0 sec 6.2.2 requires _GSB for hot-pluggable I/O APICs.
50	 */
51
52	ioapic = kzalloc(sizeof(*ioapic), GFP_KERNEL);
53	if (!ioapic)
54		return -ENOMEM;
55
56	ioapic->handle = handle;
57	ioapic->gsi_base = (u32) gsb;
58
59	if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC)
60		type = "IOAPIC";
61	else
62		type = "IOxAPIC";
63
64	ret = pci_enable_device(dev);
65	if (ret < 0)
66		goto exit_free;
67
68	pci_set_master(dev);
69
70	if (pci_request_region(dev, 0, type))
71		goto exit_disable;
72
73	res = &dev->resource[0];
74	if (acpi_register_ioapic(ioapic->handle, res->start, ioapic->gsi_base))
75		goto exit_release;
76
77	pci_set_drvdata(dev, ioapic);
78	dev_info(&dev->dev, "%s at %pR, GSI %u\n", type, res, ioapic->gsi_base);
79	return 0;
80
81exit_release:
82	pci_release_region(dev, 0);
83exit_disable:
84	pci_disable_device(dev);
85exit_free:
86	kfree(ioapic);
87	return -ENODEV;
88}
89
90static void ioapic_remove(struct pci_dev *dev)
91{
92	struct ioapic *ioapic = pci_get_drvdata(dev);
93
94	acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base);
95	pci_release_region(dev, 0);
96	pci_disable_device(dev);
97	kfree(ioapic);
98}
99
100
101static 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, },
106	{ }
107};
108
109static struct pci_driver ioapic_driver = {
110	.name		= "ioapic",
111	.id_table	= ioapic_devices,
112	.probe		= ioapic_probe,
113	.remove		= __devexit_p(ioapic_remove),
114};
115
116static int __init ioapic_init(void)
117{
118	return pci_register_driver(&ioapic_driver);
119}
120
121static void __exit ioapic_exit(void)
122{
123	pci_unregister_driver(&ioapic_driver);
124}
125
126module_init(ioapic_init);
127module_exit(ioapic_exit);
128