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.4-rc6 127 lines 2.9 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#include <acpi/acpi_bus.h> 24 25struct ioapic { 26 acpi_handle handle; 27 u32 gsi_base; 28}; 29 30static int __devinit ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent) 31{ 32 acpi_handle handle; 33 acpi_status status; 34 unsigned long long gsb; 35 struct ioapic *ioapic; 36 int ret; 37 char *type; 38 struct resource *res; 39 40 handle = DEVICE_ACPI_HANDLE(&dev->dev); 41 if (!handle) 42 return -EINVAL; 43 44 status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb); 45 if (ACPI_FAILURE(status)) 46 return -EINVAL; 47 48 /* 49 * The previous code in acpiphp evaluated _MAT if _GSB failed, but 50 * ACPI spec 4.0 sec 6.2.2 requires _GSB for hot-pluggable I/O APICs. 51 */ 52 53 ioapic = kzalloc(sizeof(*ioapic), GFP_KERNEL); 54 if (!ioapic) 55 return -ENOMEM; 56 57 ioapic->handle = handle; 58 ioapic->gsi_base = (u32) gsb; 59 60 if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC) 61 type = "IOAPIC"; 62 else 63 type = "IOxAPIC"; 64 65 ret = pci_enable_device(dev); 66 if (ret < 0) 67 goto exit_free; 68 69 pci_set_master(dev); 70 71 if (pci_request_region(dev, 0, type)) 72 goto exit_disable; 73 74 res = &dev->resource[0]; 75 if (acpi_register_ioapic(ioapic->handle, res->start, ioapic->gsi_base)) 76 goto exit_release; 77 78 pci_set_drvdata(dev, ioapic); 79 dev_info(&dev->dev, "%s at %pR, GSI %u\n", type, res, ioapic->gsi_base); 80 return 0; 81 82exit_release: 83 pci_release_region(dev, 0); 84exit_disable: 85 pci_disable_device(dev); 86exit_free: 87 kfree(ioapic); 88 return -ENODEV; 89} 90 91static void __devexit ioapic_remove(struct pci_dev *dev) 92{ 93 struct ioapic *ioapic = pci_get_drvdata(dev); 94 95 acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base); 96 pci_release_region(dev, 0); 97 pci_disable_device(dev); 98 kfree(ioapic); 99} 100 101 102static DEFINE_PCI_DEVICE_TABLE(ioapic_devices) = { 103 { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOAPIC, ~0) }, 104 { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOXAPIC, ~0) }, 105 { } 106}; 107MODULE_DEVICE_TABLE(pci, ioapic_devices); 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);