probe.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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_numaq;
  19. extern struct genapic apic_summit;
  20. extern struct genapic apic_bigsmp;
  21. extern struct genapic apic_es7000;
  22. extern struct genapic apic_default;
  23. struct genapic *genapic = &apic_default;
  24. static struct genapic *apic_probe[] __initdata = {
  25. #ifdef CONFIG_X86_NUMAQ
  26. &apic_numaq,
  27. #endif
  28. #ifdef CONFIG_X86_SUMMIT
  29. &apic_summit,
  30. #endif
  31. #ifdef CONFIG_X86_BIGSMP
  32. &apic_bigsmp,
  33. #endif
  34. #ifdef CONFIG_X86_ES7000
  35. &apic_es7000,
  36. #endif
  37. &apic_default, /* must be last */
  38. NULL,
  39. };
  40. static int cmdline_apic __initdata;
  41. static int __init parse_apic(char *arg)
  42. {
  43. int i;
  44. if (!arg)
  45. return -EINVAL;
  46. for (i = 0; apic_probe[i]; i++) {
  47. if (!strcmp(apic_probe[i]->name, arg)) {
  48. genapic = apic_probe[i];
  49. cmdline_apic = 1;
  50. return 0;
  51. }
  52. }
  53. /* Parsed again by __setup for debug/verbose */
  54. return 0;
  55. }
  56. early_param("apic", parse_apic);
  57. void __init generic_bigsmp_probe(void)
  58. {
  59. #ifdef CONFIG_X86_BIGSMP
  60. /*
  61. * This routine is used to switch to bigsmp mode when
  62. * - There is no apic= option specified by the user
  63. * - generic_apic_probe() has chosen apic_default as the sub_arch
  64. * - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support
  65. */
  66. if (!cmdline_apic && genapic == &apic_default)
  67. if (apic_bigsmp.probe()) {
  68. genapic = &apic_bigsmp;
  69. printk(KERN_INFO "Overriding APIC driver with %s\n",
  70. genapic->name);
  71. }
  72. #endif
  73. }
  74. void __init generic_apic_probe(void)
  75. {
  76. if (!cmdline_apic) {
  77. int i;
  78. for (i = 0; apic_probe[i]; i++) {
  79. if (apic_probe[i]->probe()) {
  80. genapic = apic_probe[i];
  81. break;
  82. }
  83. }
  84. /* Not visible without early console */
  85. if (!apic_probe[i])
  86. panic("Didn't find an APIC driver");
  87. }
  88. printk(KERN_INFO "Using APIC driver %s\n", genapic->name);
  89. }
  90. /* These functions can switch the APIC even after the initial ->probe() */
  91. int __init mps_oem_check(struct mp_config_table *mpc, char *oem,
  92. char *productid)
  93. {
  94. int i;
  95. for (i = 0; apic_probe[i]; ++i) {
  96. if (apic_probe[i]->mps_oem_check(mpc, oem, productid)) {
  97. if (!cmdline_apic) {
  98. genapic = apic_probe[i];
  99. printk(KERN_INFO "Switched to APIC driver `%s'.\n",
  100. genapic->name);
  101. }
  102. return 1;
  103. }
  104. }
  105. return 0;
  106. }
  107. int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
  108. {
  109. int i;
  110. for (i = 0; apic_probe[i]; ++i) {
  111. if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) {
  112. if (!cmdline_apic) {
  113. genapic = apic_probe[i];
  114. printk(KERN_INFO "Switched to APIC driver `%s'.\n",
  115. genapic->name);
  116. }
  117. return 1;
  118. }
  119. }
  120. return 0;
  121. }
  122. int hard_smp_processor_id(void)
  123. {
  124. return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID));
  125. }