Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.18-rc2 121 lines 2.8 kB view raw
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/module.h> 21#include <linux/acpi.h> 22#include <linux/slab.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 = 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 const struct pci_device_id ioapic_devices[] = { 102 { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOAPIC, ~0) }, 103 { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOXAPIC, ~0) }, 104 { } 105}; 106MODULE_DEVICE_TABLE(pci, ioapic_devices); 107 108static struct pci_driver ioapic_driver = { 109 .name = "ioapic", 110 .id_table = ioapic_devices, 111 .probe = ioapic_probe, 112 .remove = ioapic_remove, 113}; 114 115static int __init ioapic_init(void) 116{ 117 return pci_register_driver(&ioapic_driver); 118} 119module_init(ioapic_init); 120 121MODULE_LICENSE("GPL");