ioapic.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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. 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 = 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 const struct pci_device_id ioapic_devices[] = {
  82. { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOAPIC, ~0) },
  83. { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOXAPIC, ~0) },
  84. { }
  85. };
  86. MODULE_DEVICE_TABLE(pci, ioapic_devices);
  87. static struct pci_driver ioapic_driver = {
  88. .name = "ioapic",
  89. .id_table = ioapic_devices,
  90. .probe = ioapic_probe,
  91. .remove = ioapic_remove,
  92. };
  93. static int __init ioapic_init(void)
  94. {
  95. return pci_register_driver(&ioapic_driver);
  96. }
  97. module_init(ioapic_init);
  98. MODULE_LICENSE("GPL");