k8-bus_64.c 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #include <linux/init.h>
  2. #include <linux/pci.h>
  3. #include <asm/mpspec.h>
  4. #include <linux/cpumask.h>
  5. /*
  6. * This discovers the pcibus <-> node mapping on AMD K8.
  7. *
  8. * RED-PEN need to call this again on PCI hotplug
  9. * RED-PEN empty cpus get reported wrong
  10. */
  11. #define NODE_ID_REGISTER 0x60
  12. #define NODE_ID(dword) (dword & 0x07)
  13. #define LDT_BUS_NUMBER_REGISTER_0 0x94
  14. #define LDT_BUS_NUMBER_REGISTER_1 0xB4
  15. #define LDT_BUS_NUMBER_REGISTER_2 0xD4
  16. #define NR_LDT_BUS_NUMBER_REGISTERS 3
  17. #define SECONDARY_LDT_BUS_NUMBER(dword) ((dword >> 8) & 0xFF)
  18. #define SUBORDINATE_LDT_BUS_NUMBER(dword) ((dword >> 16) & 0xFF)
  19. #define PCI_DEVICE_ID_K8HTCONFIG 0x1100
  20. /**
  21. * fill_mp_bus_to_cpumask()
  22. * fills the mp_bus_to_cpumask array based according to the LDT Bus Number
  23. * Registers found in the K8 northbridge
  24. */
  25. __init static int
  26. fill_mp_bus_to_cpumask(void)
  27. {
  28. struct pci_dev *nb_dev = NULL;
  29. int i, j;
  30. u32 ldtbus, nid;
  31. static int lbnr[3] = {
  32. LDT_BUS_NUMBER_REGISTER_0,
  33. LDT_BUS_NUMBER_REGISTER_1,
  34. LDT_BUS_NUMBER_REGISTER_2
  35. };
  36. while ((nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
  37. PCI_DEVICE_ID_K8HTCONFIG, nb_dev))) {
  38. pci_read_config_dword(nb_dev, NODE_ID_REGISTER, &nid);
  39. for (i = 0; i < NR_LDT_BUS_NUMBER_REGISTERS; i++) {
  40. pci_read_config_dword(nb_dev, lbnr[i], &ldtbus);
  41. /*
  42. * if there are no busses hanging off of the current
  43. * ldt link then both the secondary and subordinate
  44. * bus number fields are set to 0.
  45. *
  46. * RED-PEN
  47. * This is slightly broken because it assumes
  48. * HT node IDs == Linux node ids, which is not always
  49. * true. However it is probably mostly true.
  50. */
  51. if (!(SECONDARY_LDT_BUS_NUMBER(ldtbus) == 0
  52. && SUBORDINATE_LDT_BUS_NUMBER(ldtbus) == 0)) {
  53. for (j = SECONDARY_LDT_BUS_NUMBER(ldtbus);
  54. j <= SUBORDINATE_LDT_BUS_NUMBER(ldtbus);
  55. j++) {
  56. struct pci_bus *bus;
  57. struct pci_sysdata *sd;
  58. long node = NODE_ID(nid);
  59. /* Algorithm a bit dumb, but
  60. it shouldn't matter here */
  61. bus = pci_find_bus(0, j);
  62. if (!bus)
  63. continue;
  64. if (!node_online(node))
  65. node = 0;
  66. sd = bus->sysdata;
  67. sd->node = node;
  68. }
  69. }
  70. }
  71. }
  72. return 0;
  73. }
  74. fs_initcall(fill_mp_bus_to_cpumask);