Subject: Re: MI SONIC Ethernet driver for mac68k
To: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
From: Jason Thorpe <thorpej@shagadelic.org>
List: port-m68k
Date: 06/06/2007 22:06:55
On Jun 6, 2007, at 9:54 AM, Izumi Tsutsui wrote:
> 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
Not too bad! Please check in the bus_dma enhancements!
>
>
> ---
> 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:
-- thorpej