Skip to content

Commit 316e8d7

Browse files
committed
pci_iounmap'2: Electric Boogaloo: try to make sense of it all
Nathan Chancellor reports that the recent change to pci_iounmap in commit 9caea00 ("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: 9caea00 ("parisc: Declare pci_iounmap() parisc version only when CONFIG_PCI enabled") Reported-by: Nathan Chancellor <[email protected]> Cc: Helge Deller <[email protected]> Cc: Arnd Bergmann <[email protected]> Cc: Guenter Roeck <[email protected]> Cc: Ulrich Teichert <[email protected]> Cc: James Bottomley <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 20621d2 commit 316e8d7

File tree

2 files changed

+46
-23
lines changed

2 files changed

+46
-23
lines changed

include/asm-generic/io.h

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,16 +1023,7 @@ static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
10231023
port &= IO_SPACE_LIMIT;
10241024
return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port;
10251025
}
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
10361027
#endif
10371028

10381029
#ifndef ioport_unmap
@@ -1048,21 +1039,10 @@ extern void ioport_unmap(void __iomem *p);
10481039
#endif /* CONFIG_HAS_IOPORT_MAP */
10491040

10501041
#ifndef CONFIG_GENERIC_IOMAP
1051-
struct pci_dev;
1052-
extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
1053-
1054-
#ifndef __pci_ioport_unmap
1055-
static inline void __pci_ioport_unmap(void __iomem *p) {}
1056-
#endif
1057-
10581042
#ifndef pci_iounmap
1059-
#define pci_iounmap pci_iounmap
1060-
static inline void pci_iounmap(struct pci_dev *dev, void __iomem *p)
1061-
{
1062-
__pci_ioport_unmap(p);
1063-
}
1043+
#define ARCH_WANTS_GENERIC_PCI_IOUNMAP
1044+
#endif
10641045
#endif
1065-
#endif /* CONFIG_GENERIC_IOMAP */
10661046

10671047
#ifndef xlate_dev_mem_ptr
10681048
#define xlate_dev_mem_ptr xlate_dev_mem_ptr

lib/pci_iomap.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,47 @@ void __iomem *pci_iomap_wc(struct pci_dev *dev, int bar, unsigned long maxlen)
134134
return pci_iomap_wc_range(dev, bar, 0, maxlen);
135135
}
136136
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+
137180
#endif /* CONFIG_PCI */

0 commit comments

Comments
 (0)