diff options
| -rw-r--r-- | arch/i386/pci/mmconfig.c | 14 | ||||
| -rw-r--r-- | arch/i386/pci/pci.h | 43 | ||||
| -rw-r--r-- | arch/x86_64/pci/mmconfig.c | 12 |
3 files changed, 55 insertions, 14 deletions
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index bb1afd9e589d..0d46b7a88b3b 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c | |||
| @@ -82,16 +82,15 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus, | |||
| 82 | 82 | ||
| 83 | switch (len) { | 83 | switch (len) { |
| 84 | case 1: | 84 | case 1: |
| 85 | *value = readb(mmcfg_virt_addr + reg); | 85 | *value = mmio_config_readb(mmcfg_virt_addr + reg); |
| 86 | break; | 86 | break; |
| 87 | case 2: | 87 | case 2: |
| 88 | *value = readw(mmcfg_virt_addr + reg); | 88 | *value = mmio_config_readw(mmcfg_virt_addr + reg); |
| 89 | break; | 89 | break; |
| 90 | case 4: | 90 | case 4: |
| 91 | *value = readl(mmcfg_virt_addr + reg); | 91 | *value = mmio_config_readl(mmcfg_virt_addr + reg); |
| 92 | break; | 92 | break; |
| 93 | } | 93 | } |
| 94 | |||
| 95 | spin_unlock_irqrestore(&pci_config_lock, flags); | 94 | spin_unlock_irqrestore(&pci_config_lock, flags); |
| 96 | 95 | ||
| 97 | return 0; | 96 | return 0; |
| @@ -116,16 +115,15 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus, | |||
| 116 | 115 | ||
| 117 | switch (len) { | 116 | switch (len) { |
| 118 | case 1: | 117 | case 1: |
| 119 | writeb(value, mmcfg_virt_addr + reg); | 118 | mmio_config_writeb(mmcfg_virt_addr, value); |
| 120 | break; | 119 | break; |
| 121 | case 2: | 120 | case 2: |
| 122 | writew(value, mmcfg_virt_addr + reg); | 121 | mmio_config_writew(mmcfg_virt_addr, value); |
| 123 | break; | 122 | break; |
| 124 | case 4: | 123 | case 4: |
| 125 | writel(value, mmcfg_virt_addr + reg); | 124 | mmio_config_writel(mmcfg_virt_addr, value); |
| 126 | break; | 125 | break; |
| 127 | } | 126 | } |
| 128 | |||
| 129 | spin_unlock_irqrestore(&pci_config_lock, flags); | 127 | spin_unlock_irqrestore(&pci_config_lock, flags); |
| 130 | 128 | ||
| 131 | return 0; | 129 | return 0; |
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h index e58bae2076ad..8c66f275756f 100644 --- a/arch/i386/pci/pci.h +++ b/arch/i386/pci/pci.h | |||
| @@ -104,3 +104,46 @@ extern DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS); | |||
| 104 | extern int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus, | 104 | extern int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus, |
| 105 | unsigned int devfn); | 105 | unsigned int devfn); |
| 106 | extern int __init pci_mmcfg_arch_init(void); | 106 | extern int __init pci_mmcfg_arch_init(void); |
| 107 | |||
| 108 | /* | ||
| 109 | * AMD Fam10h CPUs are buggy, and cannot access MMIO config space | ||
| 110 | * on their northbrige except through the * %eax register. As such, you MUST | ||
| 111 | * NOT use normal IOMEM accesses, you need to only use the magic mmio-config | ||
| 112 | * accessor functions. | ||
| 113 | * In fact just use pci_config_*, nothing else please. | ||
| 114 | */ | ||
| 115 | static inline unsigned char mmio_config_readb(void __iomem *pos) | ||
| 116 | { | ||
| 117 | u8 val; | ||
| 118 | asm volatile("movb (%1),%%al" : "=a" (val) : "r" (pos)); | ||
| 119 | return val; | ||
| 120 | } | ||
| 121 | |||
| 122 | static inline unsigned short mmio_config_readw(void __iomem *pos) | ||
| 123 | { | ||
| 124 | u16 val; | ||
| 125 | asm volatile("movw (%1),%%ax" : "=a" (val) : "r" (pos)); | ||
| 126 | return val; | ||
| 127 | } | ||
| 128 | |||
| 129 | static inline unsigned int mmio_config_readl(void __iomem *pos) | ||
| 130 | { | ||
| 131 | u32 val; | ||
| 132 | asm volatile("movl (%1),%%eax" : "=a" (val) : "r" (pos)); | ||
| 133 | return val; | ||
| 134 | } | ||
| 135 | |||
| 136 | static inline void mmio_config_writeb(void __iomem *pos, u8 val) | ||
| 137 | { | ||
| 138 | asm volatile("movb %%al,(%1)" :: "a" (val), "r" (pos) : "memory"); | ||
| 139 | } | ||
| 140 | |||
| 141 | static inline void mmio_config_writew(void __iomem *pos, u16 val) | ||
| 142 | { | ||
| 143 | asm volatile("movw %%ax,(%1)" :: "a" (val), "r" (pos) : "memory"); | ||
| 144 | } | ||
| 145 | |||
| 146 | static inline void mmio_config_writel(void __iomem *pos, u32 val) | ||
| 147 | { | ||
| 148 | asm volatile("movl %%eax,(%1)" :: "a" (val), "r" (pos) : "memory"); | ||
| 149 | } | ||
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c index 65d82736987e..4095e4d66a1d 100644 --- a/arch/x86_64/pci/mmconfig.c +++ b/arch/x86_64/pci/mmconfig.c | |||
| @@ -66,13 +66,13 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus, | |||
| 66 | 66 | ||
| 67 | switch (len) { | 67 | switch (len) { |
| 68 | case 1: | 68 | case 1: |
| 69 | *value = readb(addr + reg); | 69 | *value = mmio_config_readb(addr + reg); |
| 70 | break; | 70 | break; |
| 71 | case 2: | 71 | case 2: |
| 72 | *value = readw(addr + reg); | 72 | *value = mmio_config_readw(addr + reg); |
| 73 | break; | 73 | break; |
| 74 | case 4: | 74 | case 4: |
| 75 | *value = readl(addr + reg); | 75 | *value = mmio_config_readl(addr + reg); |
| 76 | break; | 76 | break; |
| 77 | } | 77 | } |
| 78 | 78 | ||
| @@ -94,13 +94,13 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus, | |||
| 94 | 94 | ||
| 95 | switch (len) { | 95 | switch (len) { |
| 96 | case 1: | 96 | case 1: |
| 97 | writeb(value, addr + reg); | 97 | mmio_config_writeb(addr + reg, value); |
| 98 | break; | 98 | break; |
| 99 | case 2: | 99 | case 2: |
| 100 | writew(value, addr + reg); | 100 | mmio_config_writew(addr + reg, value); |
| 101 | break; | 101 | break; |
| 102 | case 4: | 102 | case 4: |
| 103 | writel(value, addr + reg); | 103 | mmio_config_writel(addr + reg, value); |
| 104 | break; | 104 | break; |
| 105 | } | 105 | } |
| 106 | 106 | ||
