ioapic.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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. * This driver manages PCI I/O APICs added by hotplug after boot. We try to
  13. * claim all I/O APIC PCI devices, but those present at boot were registered
  14. * when we parsed the ACPI MADT, so we'll fail when we try to re-register
  15. * them.
  16. */
  17. #include <linux/pci.h>
  18. #include <linux/module.h>
  19. #include <linux/acpi.h>
  20. #include <linux/slab.h>
  21. #include <acpi/acpi_bus.h>
  22. struct ioapic {
  23. acpi_handle handle;
  24. u32 gsi_base;
  25. };
  26. static int __devinit ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
  27. {
  28. acpi_handle handle;
  29. acpi_status status;
  30. unsigned long long gsb;
  31. struct ioapic *ioapic;
  32. int ret;
  33. char *type;
  34. struct resource *res;
  35. handle = DEVICE_ACPI_HANDLE(&dev->dev);
  36. if (!handle)
  37. return -EINVAL;
  38. status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);
  39. if (ACPI_FAILURE(status))
  40. return -EINVAL;
  41. /*
  42. * The previous code in acpiphp evaluated _MAT if _GSB failed, but
  43. * ACPI spec 4.0 sec 6.2.2 requires _GSB for hot-pluggable I/O APICs.
  44. */
  45. ioapic = kzalloc(sizeof(*ioapic), GFP_KERNEL);
  46. if (!ioapic)
  47. return -ENOMEM;
  48. ioapic->handle = handle;
  49. ioapic->gsi_base = (u32) gsb;
  50. if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC)
  51. type = "IOAPIC";
  52. else
  53. type = "IOxAPIC";
  54. ret = pci_enable_device(dev);
  55. if (ret < 0)
  56. goto exit_free;
  57. pci_set_master(dev);
  58. if (pci_request_region(dev, 0, type))
  59. goto exit_disable;
  60. res = &dev->resource[0];
  61. if (acpi_register_ioapic(ioapic->handle, res->start, ioapic->gsi_base))
  62. goto exit_release;
  63. pci_set_drvdata(dev, ioapic);
  64. dev_info(&dev->dev, "%s at %pR, GSI %u\n", type, res, ioapic->gsi_base);
  65. return 0;
  66. exit_release:
  67. pci_release_region(dev, 0);
  68. exit_disable:
  69. pci_disable_device(dev);
  70. exit_free:
  71. kfree(ioapic);
  72. return -ENODEV;
  73. }
  74. static void __devexit ioapic_remove(struct pci_dev *dev)
  75. {
  76. struct ioapic *ioapic = pci_get_drvdata(dev);
  77. acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base);
  78. pci_release_region(dev, 0);
  79. pci_disable_device(dev);
  80. kfree(ioapic);
  81. }
  82. static DEFINE_PCI_DEVICE_TABLE(ioapic_devices) = {
  83. { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOAPIC, ~0) },
  84. { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOXAPIC, ~0) },
  85. { }
  86. };
  87. MODULE_DEVICE_TABLE(pci, ioapic_devices);
  88. static struct pci_driver ioapic_driver = {
  89. .name = "ioapic",
  90. .id_table = ioapic_devices,
  91. .probe = ioapic_probe,
  92. .remove = __devexit_p(ioapic_remove),
  93. };
  94. static int __init ioapic_init(void)
  95. {
  96. return pci_register_driver(&ioapic_driver);
  97. }
  98. static void __exit ioapic_exit(void)
  99. {
  100. pci_unregister_driver(&ioapic_driver);
  101. }
  102. module_init(ioapic_init);
  103. module_exit(ioapic_exit);