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