pci_iounmap'2: Electric Boogaloo: try to make sense of it all

Nathan Chancellor reports that the recent change to pci_iounmap in
commit 9caea0007601 ("parisc: Declare pci_iounmap() parisc version only
when CONFIG_PCI enabled") causes build errors on arm64.

It took me about two hours to convince myself that I think I know what
the logic of that mess of #ifdef's in the <asm-generic/io.h> header file
really aim to do, and rewrite it to be easier to follow.

Famous last words.

Anyway, the code has now been lifted from that grotty header file into
lib/pci_iomap.c, and has fairly extensive comments about what the logic
is. It also avoids indirecting through another confusing (and badly
named) helper function that has other preprocessor config conditionals.

Let's see what odd architecture did something else strange in this area
to break things. But my arm64 cross build is clean.

Fixes: 9caea0007601 ("parisc: Declare pci_iounmap() parisc version only when CONFIG_PCI enabled")
Reported-by: Nathan Chancellor <nathan@kernel.org>
Cc: Helge Deller <deller@gmx.de>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Ulrich Teichert <krypton@ulrich-teichert.org>
Cc: James Bottomley <James.Bottomley@hansenpartnership.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Changed files
+46 -23
include
asm-generic
lib
+3 -23
include/asm-generic/io.h
··· 1023 1023 port &= IO_SPACE_LIMIT; 1024 1024 return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port; 1025 1025 } 1026 - #define __pci_ioport_unmap __pci_ioport_unmap 1027 - static inline void __pci_ioport_unmap(void __iomem *p) 1028 - { 1029 - uintptr_t start = (uintptr_t) PCI_IOBASE; 1030 - uintptr_t addr = (uintptr_t) p; 1031 - 1032 - if (addr >= start && addr < start + IO_SPACE_LIMIT) 1033 - return; 1034 - iounmap(p); 1035 - } 1026 + #define ARCH_HAS_GENERIC_IOPORT_MAP 1036 1027 #endif 1037 1028 1038 1029 #ifndef ioport_unmap ··· 1039 1048 #endif /* CONFIG_HAS_IOPORT_MAP */ 1040 1049 1041 1050 #ifndef CONFIG_GENERIC_IOMAP 1042 - struct pci_dev; 1043 - extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); 1044 - 1045 - #ifndef __pci_ioport_unmap 1046 - static inline void __pci_ioport_unmap(void __iomem *p) {} 1047 - #endif 1048 - 1049 1051 #ifndef pci_iounmap 1050 - #define pci_iounmap pci_iounmap 1051 - static inline void pci_iounmap(struct pci_dev *dev, void __iomem *p) 1052 - { 1053 - __pci_ioport_unmap(p); 1054 - } 1052 + #define ARCH_WANTS_GENERIC_PCI_IOUNMAP 1055 1053 #endif 1056 - #endif /* CONFIG_GENERIC_IOMAP */ 1054 + #endif 1057 1055 1058 1056 #ifndef xlate_dev_mem_ptr 1059 1057 #define xlate_dev_mem_ptr xlate_dev_mem_ptr
+43
lib/pci_iomap.c
··· 134 134 return pci_iomap_wc_range(dev, bar, 0, maxlen); 135 135 } 136 136 EXPORT_SYMBOL_GPL(pci_iomap_wc); 137 + 138 + /* 139 + * pci_iounmap() somewhat illogically comes from lib/iomap.c for the 140 + * CONFIG_GENERIC_IOMAP case, because that's the code that knows about 141 + * the different IOMAP ranges. 142 + * 143 + * But if the architecture does not use the generic iomap code, and if 144 + * it has _not_ defined it's own private pci_iounmap function, we define 145 + * it here. 146 + * 147 + * NOTE! This default implementation assumes that if the architecture 148 + * support ioport mapping (HAS_IOPORT_MAP), the ioport mapping will 149 + * be fixed to the range [ PCI_IOBASE, PCI_IOBASE+IO_SPACE_LIMIT [, 150 + * and does not need unmapping with 'ioport_unmap()'. 151 + * 152 + * If you have different rules for your architecture, you need to 153 + * implement your own pci_iounmap() that knows the rules for where 154 + * and how IO vs MEM get mapped. 155 + * 156 + * This code is odd, and the ARCH_HAS/ARCH_WANTS #define logic comes 157 + * from legacy <asm-generic/io.h> header file behavior. In particular, 158 + * it would seem to make sense to do the iounmap(p) for the non-IO-space 159 + * case here regardless, but that's not what the old header file code 160 + * did. Probably incorrectly, but this is meant to be bug-for-bug 161 + * compatible. 162 + */ 163 + #if defined(ARCH_WANTS_GENERIC_PCI_IOUNMAP) 164 + 165 + void pci_iounmap(struct pci_dev *dev, void __iomem *p) 166 + { 167 + #ifdef ARCH_HAS_GENERIC_IOPORT_MAP 168 + uintptr_t start = (uintptr_t) PCI_IOBASE; 169 + uintptr_t addr = (uintptr_t) p; 170 + 171 + if (addr >= start && addr < start + IO_SPACE_LIMIT) 172 + return; 173 + iounmap(p); 174 + #endif 175 + } 176 + EXPORT_SYMBOL(pci_iounmap); 177 + 178 + #endif /* ARCH_WANTS_GENERIC_PCI_IOUNMAP */ 179 + 137 180 #endif /* CONFIG_PCI */