Hello,
This patch should fix pci_dma_* functions for mips64, especially
on non-coherent computers (and fixes a warning).
Vivien.
--- linux/include/asm-mips64/addrspace.h Thu Aug 1 20:22:00 2002
+++ linux.patch/include/asm-mips64/addrspace.h Thu Aug 1 20:21:54 2002
@@ -58,7 +58,7 @@
#ifndef __ASSEMBLY__
#define PHYSADDR(a) ({ \
- const _ATYPE64_ _a = (a); \
+ const _ATYPE64_ _a = _ACAST64_ (a); \
_a == _ACAST32_ _a ? CPHYSADDR(_a) : XPHYSADDR(_a); })
#endif
--- linux/include/asm-mips64/scatterlist.h Thu Aug 1 20:12:14 2002
+++ linux.patch/include/asm-mips64/scatterlist.h Thu Aug 1 20:12:01 2002
@@ -4,7 +4,7 @@
struct scatterlist {
struct page * page;
unsigned int offset;
- dma_addr_t dma_address;
+ dma_addr_t address;
unsigned int length;
};
--- linux/include/asm-mips64/pci.h Thu Aug 1 21:22:41 2002
+++ linux.patch/include/asm-mips64/pci.h Thu Aug 1 21:37:46 2002
@@ -8,6 +8,7 @@
#include <linux/config.h>
#include <linux/types.h>
+#include <linux/mm.h> /* for page_address() */
#include <asm/io.h> /* for virt_to_bus() */
#ifdef __KERNEL__
@@ -126,9 +125,11 @@
BUG();
#ifdef CONFIG_NONCOHERENT_IO
- dma_cache_wback_inv((unsigned long)ptr, size);
+ if (direction != PCI_DMA_FROMDEVICE) {
+ dma_cache_wback_inv((unsigned long)ptr, size);
+ }
#endif
- return virt_to_bus(ptr);
+ return bus_to_baddr(hwdev, virt_to_bus(ptr));
}
/*
@@ -145,7 +146,11 @@
if (direction == PCI_DMA_NONE)
BUG();
- /* Nothing to do */
+#ifdef CONFIG_NONCOHERENT_IO
+ if (direction != PCI_DMA_TODEVICE) {
+ dma_cache_wback_inv((unsigned long)bus_to_virt(dma_addr), size);
+ }
+#endif
}
/* pci_unmap_{page,single} is a nop so... */
@@ -171,10 +176,12 @@
addr = (unsigned long) page_address(page) + offset;
#ifdef CONFIG_NONCOHERENT_IO
- dma_cache_wback_inv(addr, size);
+ if (direction != PCI_DMA_FROMDEVICE) {
+ dma_cache_wback_inv(addr, size);
+ }
#endif
- return virt_to_bus((void *)addr);
+ return bus_to_baddr(hwdev, virt_to_bus((void *)addr));
}
static inline void pci_unmap_page(struct pci_dev *hwdev, dma_addr_t
dma_address,
@@ -182,7 +189,12 @@
{
if (direction == PCI_DMA_NONE)
BUG();
- /* Nothing to do */
+
+#ifdef CONFIG_NONCOHERENT_IO
+ if (direction != PCI_DMA_TODEVICE) {
+ dma_cache_wback_inv((unsigned long)
bus_to_virt(baddr_to_bus(hwdev, dma_address)), size);
+ }
+#endif
}
/*
@@ -205,17 +217,20 @@
int nents, int direction)
{
int i;
+ unsigned long addr;
if (direction == PCI_DMA_NONE)
BUG();
for (i = 0; i < nents; i++, sg++) {
- dma_cache_wback_inv((unsigned long)page_address(sg->page),
- sg->length);
- sg->address = bus_to_baddr[hwdev->bus->number] +
- page_to_bus(sg->page) + sg->offset;
+ addr = (unsigned long) page_address(sg->page) + sg->offset;
+#ifdef CONFIG_NONCOHERENT_IO
+ if (direction != PCI_DMA_FROMDEVICE) {
+ dma_cache_wback_inv(addr, sg->length);
+ }
+#endif
+ sg->address = bus_to_baddr(hwdev, virt_to_bus((void *)addr));
}
-
return nents;
}
@@ -227,10 +242,22 @@
static inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
int nents, int direction)
{
+#ifdef CONFIG_NONCOHERENT_IO
+ int i;
+ unsigned long addr;
+#endif
+
if (direction == PCI_DMA_NONE)
BUG();
- /* Nothing to do */
+#ifdef CONFIG_NONCOHERENT_IO
+ if (direction != PCI_DMA_TODEVICE) {
+ for (i = 0; i < nents; i++, sg++) {
+ addr = (unsigned long) page_address(sg->page) + sg->offset;
+ dma_cache_wback_inv(addr, sg->length);
+ }
+ }
+#endif
}
/*
@@ -250,7 +277,7 @@
if (direction == PCI_DMA_NONE)
BUG();
#ifdef CONFIG_NONCOHERENT_IO
- dma_cache_wback_inv((unsigned long)__va(dma_handle -
bus_to_baddr[hwdev->bus->number]), size);
+ dma_cache_wback_inv((unsigned long) bus_to_virt(baddr_to_bus(hwdev,
dma_handle)), size);
#endif
}
@@ -267,6 +294,7 @@
{
#ifdef CONFIG_NONCOHERENT_IO
int i;
+ unsigned long addr;
#endif
if (direction == PCI_DMA_NONE)
@@ -274,9 +302,10 @@
/* Make sure that gcc doesn't leave the empty loop body. */
#ifdef CONFIG_NONCOHERENT_IO
- for (i = 0; i < nelems; i++, sg++)
- dma_cache_wback_inv((unsigned long)page_address(sg->page),
- sg->length);
+ for (i = 0; i < nelems; i++, sg++) {
+ addr = (unsigned long) page_address(sg->page) + sg->offset;
+ dma_cache_wback_inv(addr, sg->length);
+ }
#endif
}
#endif /* CONFIG_MAPPED_PCI_IO */
--- linux/include/asm-mips64/io.h Thu Aug 1 22:15:19 2002
+++ linux.patch/include/asm-mips64/io.h Thu Aug 1 22:14:57 2002
@@ -35,7 +35,14 @@
#include <asm/ip32/io.h>
#endif
+#ifdef CONFIG_SGI_IP27
extern unsigned long bus_to_baddr[256];
+#define bus_to_baddr(hwdev, addr) (bus_to_baddr[(hwdev)->bus->number] | (addr))
+#define baddr_to_bus(hwdev, addr) ((addr) - bus_to_baddr[(hwdev)->bus->number])
+#else
+#define bus_to_baddr(hwdev, addr) (addr)
+#define baddr_to_bus(hwdev, addr) (addr)
+#endif
/*
* Slowdown I/O port space accesses for antique hardware.
|