probe.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * Copyright 2003 Andi Kleen, SuSE Labs.
  3. * Subject to the GNU Public License, v.2
  4. *
  5. * Generic x86 APIC driver probe layer.
  6. */
  7. #include <linux/threads.h>
  8. #include <linux/cpumask.h>
  9. #include <linux/string.h>
  10. #include <linux/kernel.h>
  11. #include <linux/ctype.h>
  12. #include <linux/init.h>
  13. #include <linux/errno.h>
  14. #include <asm/fixmap.h>
  15. #include <asm/mpspec.h>
  16. #include <asm/apicdef.h>
  17. #include <asm/genapic.h>
  18. extern struct genapic apic_summit;
  19. extern struct genapic apic_bigsmp;
  20. extern struct genapic apic_es7000;
  21. extern struct genapic apic_default;
  22. struct genapic *genapic = &apic_default;
  23. static struct genapic *apic_probe[] __initdata = {
  24. &apic_summit,
  25. &apic_bigsmp,
  26. &apic_es7000,
  27. &apic_default, /* must be last */
  28. NULL,
  29. };
  30. static int cmdline_apic __initdata;
  31. static int __init parse_apic(char *arg)
  32. {
  33. int i;
  34. if (!arg)
  35. return -EINVAL;
  36. for (i = 0; apic_probe[i]; i++) {
  37. if (!strcmp(apic_probe[i]->name, arg)) {
  38. genapic = apic_probe[i];
  39. cmdline_apic = 1;
  40. return 0;
  41. }
  42. }
  43. /* Parsed again by __setup for debug/verbose */
  44. return 0;
  45. }
  46. early_param("apic", parse_apic);
  47. void __init generic_bigsmp_probe(void)
  48. {
  49. /*
  50. * This routine is used to switch to bigsmp mode when
  51. * - There is no apic= option specified by the user
  52. * - generic_apic_probe() has chosen apic_default as the sub_arch
  53. * - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support
  54. */
  55. if (!cmdline_apic && genapic == &apic_default)
  56. if (apic_bigsmp.probe()) {
  57. genapic = &apic_bigsmp;
  58. printk(KERN_INFO "Overriding APIC driver with %s\n",
  59. genapic->name);
  60. }
  61. }
  62. void __init generic_apic_probe(void)
  63. {
  64. if (!cmdline_apic) {
  65. int i;
  66. for (i = 0; apic_probe[i]; i++) {
  67. if (apic_probe[i]->probe()) {
  68. genapic = apic_probe[i];
  69. break;
  70. }
  71. }
  72. /* Not visible without early console */
  73. if (!apic_probe[i])
  74. panic("Didn't find an APIC driver");
  75. }
  76. printk(KERN_INFO "Using APIC driver %s\n", genapic->name);
  77. }
  78. /* These functions can switch the APIC even after the initial ->probe() */
  79. int __init mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid)
  80. {
  81. int i;
  82. for (i = 0; apic_probe[i]; ++i) {
  83. if (apic_probe[i]->mps_oem_check(mpc, oem, productid)) {
  84. if (!cmdline_apic) {
  85. genapic = apic_probe[i];
  86. printk(KERN_INFO "Switched to APIC driver `%s'.\n",
  87. genapic->name);
  88. }
  89. return 1;
  90. }
  91. }
  92. return 0;
  93. }
  94. int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
  95. {
  96. int i;
  97. for (i = 0; apic_probe[i]; ++i) {
  98. if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) {
  99. if (!cmdline_apic) {
  100. genapic = apic_probe[i];
  101. printk(KERN_INFO "Switched to APIC driver `%s'.\n",
  102. genapic->name);
  103. }
  104. return 1;
  105. }
  106. }
  107. return 0;
  108. }
  109. int hard_smp_processor_id(void)
  110. {
  111. return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID));
  112. }