Subject: PCI patch of the day

From: Carsten Langgaard <[email-masked]>
Date: Wed, 07 Aug 2002 10:20:39 +0200

It's apparently not that easy to get the PCI code right, the current
code won't compile, so here is the patch of the day.

/Carsten

--
_    _ ____  ___   Carsten Langgaard   Mailto:[email-masked]
|\  /|||___)(___   MIPS Denmark        Direct: +45 4486 5527
| \/ |||    ____)  Lautrupvang 4B      Switch: +45 4486 5555
  TECHNOLOGIES     2750 Ballerup       Fax...: +45 4486 5556
                   Denmark             http://www.mips.com

Index: include/asm-mips/pci.h
===================================================================
RCS file: /cvs/linux/include/asm-mips/pci.h,v
retrieving revision 1.24.2.10
diff -u -r1.24.2.10 pci.h
--- include/asm-mips/pci.h	2002/08/07 03:33:30	1.24.2.10
+++ include/asm-mips/pci.h	2002/08/07 08:06:54
@@ -120,8 +120,8 @@
 	if (direction != PCI_DMA_TODEVICE) {
 		unsigned long addr;
 
-		addr = bus_to_virt(baddr_to_bus(hwdev, dma_address));
-		dma_cache_back_inv(addr, size);
+		addr = (dma_addr_t)bus_to_virt(baddr_to_bus(hwdev, dma_addr));
+		dma_cache_wback_inv(addr, size);
 	}
 }
 
@@ -153,8 +153,8 @@
 	if (direction != PCI_DMA_TODEVICE) {
 		unsigned long addr;
 
-		addr = bus_to_virt(baddr_to_bus(hwdev, dma_address));
-		dma_cache_back_inv(addr, size);
+		addr = (dma_addr_t)bus_to_virt(baddr_to_bus(hwdev, dma_address));
+		dma_cache_wback_inv(addr, size);
 	}
 }
 
@@ -255,7 +255,7 @@
 	if (direction == PCI_DMA_NONE)
 		out_of_line_bug();
 
-	addr = dma_handle - bus_to_baddr(hwdev->bus->number) + PAGE_OFFSET;
+	addr = (dma_addr_t)bus_to_virt(baddr_to_bus(hwdev->bus->number, dma_handle));
 	dma_cache_wback_inv(addr, size);
 }
 
Index: include/asm-mips64/pci.h
===================================================================
RCS file: /cvs/linux/include/asm-mips64/pci.h,v
retrieving revision 1.16.2.11
diff -u -r1.16.2.11 pci.h
--- include/asm-mips64/pci.h	2002/08/07 03:33:30	1.16.2.11
+++ include/asm-mips64/pci.h	2002/08/07 08:06:55
@@ -146,8 +146,8 @@
 	if (direction != PCI_DMA_TODEVICE) {
 		unsigned long addr;
 
-		addr = bus_to_virt(baddr_to_bus(hwdev, dma_address));
-		dma_cache_back_inv(addr, size);
+		addr = (dma_addr_t)bus_to_virt(baddr_to_bus(hwdev, dma_addr));
+		dma_cache_wback_inv(addr, size);
 	}
 }
 
@@ -187,8 +187,8 @@
 	if (direction != PCI_DMA_TODEVICE) {
 		unsigned long addr;
 
-		addr = bus_to_virt(baddr_to_bus(hwdev, dma_address));
-		dma_cache_back_inv(addr, size);
+		addr = (dma_addr_t)bus_to_virt(baddr_to_bus(hwdev, dma_address));
+		dma_cache_wback_inv(addr, size);
 	}
 }
 
@@ -281,7 +281,7 @@
 	if (direction == PCI_DMA_NONE)
 		out_of_line_bug();
 
-	addr = dma_handle - bus_to_baddr(hwdev->bus->number) + PAGE_OFFSET;
+	addr = (dma_addr_t)bus_to_virt(baddr_to_bus(hwdev->bus->number, dma_handle));
 	dma_cache_wback_inv(addr, size);
 }

---

From: Ralf Baechle <[email-masked]>
Date: Wed, 7 Aug 2002 12:09:38 +0200

> code won't compile, so here is the patch of the day.

Sigh, yes.  The whole flushing thing was done improperly and the patches
to fix that which I was integrating last night were not right either.  The
big question for me is why nobody was complaining or is suddently everybody
only using coherent machines ...

And all the DAC stuff also wants to be implemented.  We've got a bunch of
cruel hacks for the sake of IP27 and want to get rid of those.  The god
news is that now 32-bit and 64-bit pci.h are identical :-)

  Ralf

---

From: William Jhun <[email-masked]>
Date: Wed, 7 Aug 2002 09:38:28 -0700

Ralf,

Will the *_dma_cache_wback() routines ever be implemented? I sent out a
set of patches a while ago that defaults them to calling _wback_inv()
instead of calling panic(). Additionally I sent out some PCI DMA
coherency patches that would, for pci_map_*():

- Invalidate if DMAing from the device
- Writeback if DMAing to the device
- Writeback/Invalidate if bidirectional

pci_dma_sync_*() was changed to simply invalidate if DMAing from the
device or bidirectional. Conceivably, the pci_unmap_*() should
invalidate as well, since the following could happen:

- pci_dma_sync_*()
- driver reads out of buffer
- DMA happens again
- pci_unmap_*()
- buffer cachelines better be invalidated!

Not to mention that the whole PCI DMA interface is inherently broken.
I've cogitated on this and sent patches to those responsible, but was
told to buzz off. The above is a good example of this broken-ness:
you'll have an extra invalidate for no reason if you never end up using
pci_dma_sync_*() but just simply map, DMA and unmap. Otherwise, it'll be
broken for the pci_dma_sync_*() case. And I've already went on before
about how streaming mappings are broken for PCI_DMA_TODEVICE when
re-using one buffer.

I've already spent a lot of time trying to sort this out and get the
patches right, but since I received almost zero response I dropped it.
Apparently it's still broken enough to need further attention.

Will