Subject: Re: MI SONIC Ethernet driver for mac68k
To: None <port-mac68k@NetBSD.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: port-mac68k
Date: 06/07/2007 01:54:57
I wrote:
> Summary:
> TX on sn0 RX on sn0
> MD: 1026KB/s 846KB/s
> MI: 793KB/s 854KB/s
more results:
MI driver with BUS_DMA_COHERENT support:
TX on sn0 RX on sn0
842KB/s 888KB/s
MI driver with BUS_DMA_COHERENT support and 16bytes TX DMA threshold:
TX on sn0 RX on sn0
903KB/s 886KB/s
---
Izumi Tsutsui
Index: arch/m68k/include/bus_dma.h
===================================================================
RCS file: /cvsroot/src/sys/arch/m68k/include/bus_dma.h,v
retrieving revision 1.8
diff -u -r1.8 bus_dma.h
--- arch/m68k/include/bus_dma.h 4 Mar 2007 06:00:04 -0000 1.8
+++ arch/m68k/include/bus_dma.h 6 Jun 2007 16:48:19 -0000
@@ -119,6 +119,7 @@
struct m68k_bus_dma_segment {
bus_addr_t ds_addr; /* DMA address */
bus_size_t ds_len; /* length of transfer */
+ u_int _ds_flags; /* MD flags */
};
typedef struct m68k_bus_dma_segment bus_dma_segment_t;
@@ -215,7 +216,7 @@
int _dm_segcnt; /* number of segs this map can map */
bus_size_t _dm_maxmaxsegsz; /* fixed largest possible segment */
bus_size_t _dm_boundary; /* don't cross this */
- int _dm_flags; /* misc. flags */
+ u_int _dm_flags; /* misc. flags */
/* Machine dependant fields: */
bus_size_t dm_xfer_len; /* length of successful transfer */
Index: arch/m68k/include/pmap_motorola.h
===================================================================
RCS file: /cvsroot/src/sys/arch/m68k/include/pmap_motorola.h,v
retrieving revision 1.13
diff -u -r1.13 pmap_motorola.h
--- arch/m68k/include/pmap_motorola.h 12 May 2007 17:43:53 -0000 1.13
+++ arch/m68k/include/pmap_motorola.h 6 Jun 2007 16:48:19 -0000
@@ -202,10 +202,8 @@
#define PMAP_PREFER(foff, vap, sz, td) pmap_prefer((foff), (vap))
#endif
-#ifdef mvme68k
void _pmap_set_page_cacheable(struct pmap *, vaddr_t);
void _pmap_set_page_cacheinhibit(struct pmap *, vaddr_t);
int _pmap_page_is_cacheable(struct pmap *, vaddr_t);
-#endif
#endif /* !_M68K_PMAP_MOTOROLA_H_ */
Index: arch/m68k/m68k/bus_dma.c
===================================================================
RCS file: /cvsroot/src/sys/arch/m68k/m68k/bus_dma.c,v
retrieving revision 1.23
diff -u -r1.23 bus_dma.c
--- arch/m68k/m68k/bus_dma.c 2 Jun 2007 11:13:45 -0000 1.23
+++ arch/m68k/m68k/bus_dma.c 6 Jun 2007 16:48:19 -0000
@@ -141,23 +141,30 @@
bus_size_t sgsize;
bus_addr_t curaddr, lastaddr, baddr, bmask;
vaddr_t vaddr = (vaddr_t)buf;
- int seg;
+ int seg, cacheable, coherent;
+ pmap_t pmap;
bool rv;
+ coherent = BUS_DMA_COHERENT;
lastaddr = *lastaddrp;
bmask = ~(map->_dm_boundary - 1);
+ if (!VMSPACE_IS_KERNEL_P(vm))
+ pmap = vm_map_pmap(&vm->vm_map);
+ else
+ pmap = pmap_kernel();
for (seg = *segp; buflen > 0 ; ) {
/*
* Get the physical address for this segment.
*/
- if (!VMSPACE_IS_KERNEL_P(vm))
- rv = pmap_extract(vm_map_pmap(&vm->vm_map),
- vaddr, &curaddr);
- else
- rv = pmap_extract(pmap_kernel(), vaddr, &curaddr);
+ rv = pmap_extract(pmap, vaddr, &curaddr);
KASSERT(rv);
+ cacheable = _pmap_page_is_cacheable(pmap, vaddr);
+
+ if (cacheable)
+ coherent = 0;
+
/*
* Compute the segment size, and adjust counts.
*/
@@ -181,6 +188,8 @@
if (first) {
map->dm_segs[seg].ds_addr = curaddr;
map->dm_segs[seg].ds_len = sgsize;
+ map->dm_segs[seg]._ds_flags =
+ cacheable ? 0 : BUS_DMA_COHERENT;
first = 0;
} else {
if (curaddr == lastaddr &&
@@ -195,6 +204,8 @@
break;
map->dm_segs[seg].ds_addr = curaddr;
map->dm_segs[seg].ds_len = sgsize;
+ map->dm_segs[seg]._ds_flags =
+ cacheable ? 0 : BUS_DMA_COHERENT;
}
}
@@ -205,6 +216,9 @@
*segp = seg;
*lastaddrp = lastaddr;
+ map->_dm_flags &= ~BUS_DMA_COHERENT;
+ /* BUS_DMA_COHERENT is set only if all segments are uncached */
+ map->_dm_flags |= coherent;
/*
* Did we fit?
@@ -408,6 +422,7 @@
map->dm_maxsegsz = map->_dm_maxmaxsegsz;
map->dm_mapsize = 0;
map->dm_nsegs = 0;
+ map->_dm_flags &= ~BUS_DMA_COHERENT;
}
/*
@@ -426,6 +441,7 @@
#if defined(M68040) || defined(M68060)
bus_addr_t p, e, ps, pe;
bus_size_t seglen;
+ bus_dma_segment_t *seg;
int i;
#endif
@@ -438,6 +454,10 @@
#endif
#if defined(M68040) || defined(M68060)
+ /* If the whole DMA map is uncached, do nothing. */
+ if ((map->_dm_flags & BUS_DMA_COHERENT) != 0)
+ return;
+
/* Short-circuit for unsupported `ops' */
if ((ops & (BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)) == 0)
return;
@@ -446,9 +466,10 @@
* flush/purge the cache.
*/
for (i = 0; i < map->dm_nsegs && len != 0; i++) {
- if (map->dm_segs[i].ds_len <= offset) {
+ seg = &map->dm_segs[i];
+ if (seg->ds_len <= offset) {
/* Segment irrelevant - before requested offset */
- offset -= map->dm_segs[i].ds_len;
+ offset -= seg->ds_len;
continue;
}
@@ -457,11 +478,15 @@
* each segment until we have exhausted the
* length.
*/
- seglen = map->dm_segs[i].ds_len - offset;
+ seglen = seg->ds_len - offset;
if (seglen > len)
seglen = len;
- ps = map->dm_segs[i].ds_addr + offset;
+ /* Ignore cache-inhibited segments */
+ if ((seg->_ds_flags & BUS_DMA_COHERENT) != 0)
+ continue;
+
+ ps = seg->ds_addr + offset;
pe = ps + seglen;
if (ops & BUS_DMASYNC_PREWRITE) {
@@ -655,10 +680,20 @@
pmap_enter(pmap_kernel(), va, addr,
VM_PROT_READ | VM_PROT_WRITE,
VM_PROT_READ | VM_PROT_WRITE | PMAP_WIRED);
+
+ /* Cache-inhibit the page if necessary */
+ if ((flags & BUS_DMA_COHERENT) != 0)
+ _pmap_set_page_cacheinhibit(pmap_kernel(), va);
+
+ segs[curseg]._ds_flags &= ~BUS_DMA_COHERENT;
+ segs[curseg]._ds_flags |= (flags & BUS_DMA_COHERENT);
}
}
pmap_update(pmap_kernel());
+ if ((flags & BUS_DMA_COHERENT) != 0)
+ TBIAS();
+
return 0;
}
@@ -669,6 +704,8 @@
void
_bus_dmamem_unmap(bus_dma_tag_t t, void *kva, size_t size)
{
+ vaddr_t va;
+ size_t s;
#ifdef DIAGNOSTIC
if ((u_long)kva & PGOFSET)
@@ -677,6 +714,15 @@
size = round_page(size);
+ /*
+ * Re-enable cacheing on the range
+ * XXXSCW: There should be some way to indicate that the pages
+ * were mapped DMA_MAP_COHERENT in the first place...
+ */
+ for (s = 0, va = (vaddr_t)kva; s < size;
+ s += PAGE_SIZE, va += PAGE_SIZE)
+ _pmap_set_page_cacheable(pmap_kernel(), va);
+
pmap_remove(pmap_kernel(), (vaddr_t)kva, (vaddr_t)kva + size);
pmap_update(pmap_kernel());
uvm_km_free(kernel_map, (vaddr_t)kva, size, UVM_KMF_VAONLY);
@@ -707,6 +753,10 @@
continue;
}
+ /*
+ * XXXSCW: What about BUS_DMA_COHERENT ??
+ */
+
return m68k_btop((char *)segs[i].ds_addr + off);
}
Index: arch/m68k/m68k/pmap_motorola.c
===================================================================
RCS file: /cvsroot/src/sys/arch/m68k/m68k/pmap_motorola.c,v
retrieving revision 1.30
diff -u -r1.30 pmap_motorola.c
--- arch/m68k/m68k/pmap_motorola.c 18 May 2007 01:46:40 -0000 1.30
+++ arch/m68k/m68k/pmap_motorola.c 6 Jun 2007 16:48:20 -0000
@@ -2848,8 +2848,6 @@
(void)cachectl1(0x80000004, va, len, p);
}
-#ifdef mvme68k
-
void
_pmap_set_page_cacheable(pmap_t pmap, vaddr_t va)
{
@@ -2905,8 +2903,6 @@
return (pmap_pte_ci(pmap_pte(pmap, va)) == 0) ? 1 : 0;
}
-#endif /* mvme68k */
-
#ifdef DEBUG
/*
* pmap_pvdump: