mmconfig_32.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * Copyright (C) 2004 Matthew Wilcox <matthew@wil.cx>
  3. * Copyright (C) 2004 Intel Corp.
  4. *
  5. * This code is released under the GNU General Public License version 2.
  6. */
  7. /*
  8. * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
  9. */
  10. #include <linux/pci.h>
  11. #include <linux/init.h>
  12. #include <linux/rcupdate.h>
  13. #include <asm/e820.h>
  14. #include <asm/pci_x86.h>
  15. #include <acpi/acpi.h>
  16. /* Assume systems with more busses have correct MCFG */
  17. #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
  18. /* The base address of the last MMCONFIG device accessed */
  19. static u32 mmcfg_last_accessed_device;
  20. static int mmcfg_last_accessed_cpu;
  21. /*
  22. * Functions for accessing PCI configuration space with MMCONFIG accesses
  23. */
  24. static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
  25. {
  26. struct pci_mmcfg_region *cfg = pci_mmconfig_lookup(seg, bus);
  27. if (cfg)
  28. return cfg->address;
  29. return 0;
  30. }
  31. /*
  32. * This is always called under pci_config_lock
  33. */
  34. static void pci_exp_set_dev_base(unsigned int base, int bus, int devfn)
  35. {
  36. u32 dev_base = base | PCI_MMCFG_BUS_OFFSET(bus) | (devfn << 12);
  37. int cpu = smp_processor_id();
  38. if (dev_base != mmcfg_last_accessed_device ||
  39. cpu != mmcfg_last_accessed_cpu) {
  40. mmcfg_last_accessed_device = dev_base;
  41. mmcfg_last_accessed_cpu = cpu;
  42. set_fixmap_nocache(FIX_PCIE_MCFG, dev_base);
  43. }
  44. }
  45. static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
  46. unsigned int devfn, int reg, int len, u32 *value)
  47. {
  48. unsigned long flags;
  49. u32 base;
  50. if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
  51. err: *value = -1;
  52. return -EINVAL;
  53. }
  54. rcu_read_lock();
  55. base = get_base_addr(seg, bus, devfn);
  56. if (!base) {
  57. rcu_read_unlock();
  58. goto err;
  59. }
  60. raw_spin_lock_irqsave(&pci_config_lock, flags);
  61. pci_exp_set_dev_base(base, bus, devfn);
  62. switch (len) {
  63. case 1:
  64. *value = mmio_config_readb(mmcfg_virt_addr + reg);
  65. break;
  66. case 2:
  67. *value = mmio_config_readw(mmcfg_virt_addr + reg);
  68. break;
  69. case 4:
  70. *value = mmio_config_readl(mmcfg_virt_addr + reg);
  71. break;
  72. }
  73. raw_spin_unlock_irqrestore(&pci_config_lock, flags);
  74. rcu_read_unlock();
  75. return 0;
  76. }
  77. static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
  78. unsigned int devfn, int reg, int len, u32 value)
  79. {
  80. unsigned long flags;
  81. u32 base;
  82. if ((bus > 255) || (devfn > 255) || (reg > 4095))
  83. return -EINVAL;
  84. rcu_read_lock();
  85. base = get_base_addr(seg, bus, devfn);
  86. if (!base) {
  87. rcu_read_unlock();
  88. return -EINVAL;
  89. }
  90. raw_spin_lock_irqsave(&pci_config_lock, flags);
  91. pci_exp_set_dev_base(base, bus, devfn);
  92. switch (len) {
  93. case 1:
  94. mmio_config_writeb(mmcfg_virt_addr + reg, value);
  95. break;
  96. case 2:
  97. mmio_config_writew(mmcfg_virt_addr + reg, value);
  98. break;
  99. case 4:
  100. mmio_config_writel(mmcfg_virt_addr + reg, value);
  101. break;
  102. }
  103. raw_spin_unlock_irqrestore(&pci_config_lock, flags);
  104. rcu_read_unlock();
  105. return 0;
  106. }
  107. const struct pci_raw_ops pci_mmcfg = {
  108. .read = pci_mmcfg_read,
  109. .write = pci_mmcfg_write,
  110. };
  111. int __init pci_mmcfg_arch_init(void)
  112. {
  113. printk(KERN_INFO "PCI: Using MMCONFIG for extended config space\n");
  114. raw_pci_ext_ops = &pci_mmcfg;
  115. return 1;
  116. }
  117. void __init pci_mmcfg_arch_free(void)
  118. {
  119. }
  120. int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg)
  121. {
  122. return 0;
  123. }
  124. void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg)
  125. {
  126. unsigned long flags;
  127. /* Invalidate the cached mmcfg map entry. */
  128. raw_spin_lock_irqsave(&pci_config_lock, flags);
  129. mmcfg_last_accessed_device = 0;
  130. raw_spin_unlock_irqrestore(&pci_config_lock, flags);
  131. }