diff options
author | Roland Dreier <rdreier@cisco.com> | 2006-12-06 18:15:38 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-12-08 01:10:18 -0500 |
commit | 1d4454e7ce30239e67b154ae08f6d906b9737334 (patch) | |
tree | 293946b4886a2b9cae9e70479cdd2ab678dd94c4 /include/asm-powerpc | |
parent | 885ed0fb484cc2d0a539558edf47a2a7c4fdd664 (diff) |
[POWERPC] Define pci_unmap_addr() et al. when CONFIG_NOT_COHERENT_CACHE=y
The current PowerPC code makes pci_unmap_addr(), pci_unmap_addr_set(),
and friends trivial for all 32-bit kernels. This is reasonable, since
for those kernels it is true that pci_unmap_single() does not need the
DMA address from the original DMA mapping -- in fact, it is a NOP.
However, I recently tried the tg3 driver on a PowerPC 440SPe machine,
which runs a 32-bit kernel and has non-cache-coherent PCI DMA. I
found that the tg3 driver crashed in pci_dma_sync_single_for_cpu(),
since for non-coherent systems, that function must invalidate the
cache for the DMA address range requested, and therefore it does use
the address passed in. tg3 uses a DMA address it stashes away with
pci_unmap_addr_set() and retrieves with pci_unmap_addr(). Of course,
since pci_unmap_addr() is defined to (0) right now, this doesn't work.
It seems to me that the tg3 driver is using pci_unmap_addr() in a
legitimate way -- I wouldn't want to have to teach all drivers that
they should use pci_unmap_addr() if they only need the address for
unmapping functions, but if they want the pci_dma_sync functions, then
they have to store the DMA address without the helper macros.
The right fix therefore seems to be in the definition of the macros in
<asm/pci.h> -- we should use the trivial versions only for 32-bit
kernels for coherent systems, and the real versions for both 64-bit
kernels and non-coherent systems.
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'include/asm-powerpc')
-rw-r--r-- | include/asm-powerpc/pci.h | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h index 16f13319c769..ac656ee6bb19 100644 --- a/include/asm-powerpc/pci.h +++ b/include/asm-powerpc/pci.h | |||
@@ -143,8 +143,13 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, | |||
143 | /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */ | 143 | /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */ |
144 | #define HAVE_PCI_MMAP 1 | 144 | #define HAVE_PCI_MMAP 1 |
145 | 145 | ||
146 | #ifdef CONFIG_PPC64 | 146 | #if defined(CONFIG_PPC64) || defined(CONFIG_NOT_COHERENT_CACHE) |
147 | /* pci_unmap_{single,page} is not a nop, thus... */ | 147 | /* |
148 | * For 64-bit kernels, pci_unmap_{single,page} is not a nop. | ||
149 | * For 32-bit non-coherent kernels, pci_dma_sync_single_for_cpu() and | ||
150 | * so on are not nops. | ||
151 | * and thus... | ||
152 | */ | ||
148 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ | 153 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ |
149 | dma_addr_t ADDR_NAME; | 154 | dma_addr_t ADDR_NAME; |
150 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \ | 155 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \ |
@@ -158,6 +163,20 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, | |||
158 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ | 163 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ |
159 | (((PTR)->LEN_NAME) = (VAL)) | 164 | (((PTR)->LEN_NAME) = (VAL)) |
160 | 165 | ||
166 | #else /* 32-bit && coherent */ | ||
167 | |||
168 | /* pci_unmap_{page,single} is a nop so... */ | ||
169 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) | ||
170 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) | ||
171 | #define pci_unmap_addr(PTR, ADDR_NAME) (0) | ||
172 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0) | ||
173 | #define pci_unmap_len(PTR, LEN_NAME) (0) | ||
174 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) | ||
175 | |||
176 | #endif /* CONFIG_PPC64 || CONFIG_NOT_COHERENT_CACHE */ | ||
177 | |||
178 | #ifdef CONFIG_PPC64 | ||
179 | |||
161 | /* The PCI address space does not equal the physical memory address | 180 | /* The PCI address space does not equal the physical memory address |
162 | * space (we have an IOMMU). The IDE and SCSI device layers use | 181 | * space (we have an IOMMU). The IDE and SCSI device layers use |
163 | * this boolean for bounce buffer decisions. | 182 | * this boolean for bounce buffer decisions. |
@@ -172,16 +191,8 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, | |||
172 | */ | 191 | */ |
173 | #define PCI_DMA_BUS_IS_PHYS (1) | 192 | #define PCI_DMA_BUS_IS_PHYS (1) |
174 | 193 | ||
175 | /* pci_unmap_{page,single} is a nop so... */ | ||
176 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) | ||
177 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) | ||
178 | #define pci_unmap_addr(PTR, ADDR_NAME) (0) | ||
179 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0) | ||
180 | #define pci_unmap_len(PTR, LEN_NAME) (0) | ||
181 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) | ||
182 | |||
183 | #endif /* CONFIG_PPC64 */ | 194 | #endif /* CONFIG_PPC64 */ |
184 | 195 | ||
185 | extern void pcibios_resource_to_bus(struct pci_dev *dev, | 196 | extern void pcibios_resource_to_bus(struct pci_dev *dev, |
186 | struct pci_bus_region *region, | 197 | struct pci_bus_region *region, |
187 | struct resource *res); | 198 | struct resource *res); |