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