Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 19 Dec 2012 09:56:28 +0100
From:      Hans Petter Selasky <hselasky@c2i.net>
To:        Warner Losh <imp@bsdimp.com>
Cc:        Oleksandr Tymoshenko <gonzo@freebsd.org>, Andrew Turner <andrew@fubar.geek.nz>, freebsd-usb@freebsd.org
Subject:   Re: EHCI on armv6 with Write-Back caches
Message-ID:  <201212190956.28609.hselasky@c2i.net>
In-Reply-To: <1482FC19-720A-480A-BAD2-C8CD306E2E5F@bsdimp.com>
References:  <20121218204931.5322922d@fubar.geek.nz> <201212182044.11326.hselasky@c2i.net> <1482FC19-720A-480A-BAD2-C8CD306E2E5F@bsdimp.com>

next in thread | previous in thread | raw e-mail | index | archive | help
Hi again,

Different vendors use different naming conventions about sync operations. 
Maybe we should start defining some names and agree about that first?

usb_pc_cpu_flush:

This function is a system abstraction which is supposed to ensure that all CPU 
cached data for the given buffer is written to RAM before this function 
returns.

usb_pc_cpu_invalidate:

This function is a system abstraction which is supposed to ensure that all CPU 
cached data is cleared for the given buffer.

These functions have been carefully added in all the USB drivers using DMA.

Atomicity:

I understand that the ARM hardware is not always compatible to this approach.

1) Flushing data to RAM is not a problem in any case? Do you agree?

2) Invalidating data is a problem, because invalidation can cause nearby data 
to be cleared aswell. So basically for those systems which are not handling 
this, flushing data means a lock of all CPU's until the flush/invalidate 
sequence is complete? Any dispute about this?

If the CPU does not support certain features we cannot have an efficient 
system. It is like having a CPU which doesn't support switching off interrupt 
levels, like an 8-bit AVR. Then no matter how you twist it, you cannot 
postpone an interrupt to a software thread. Same goes for DMA support. If 
their DMA engine doesn't support byte granularity and possibility to 
flush/invalidate on a per-byte basis, then implement a global system lock to 
flush/invalidate data like I suggest, if this is not doable in the hardware by 
the CPU instruction set.

The approach that I was recommended several years ago, is that I can pass a 
pointer to a buffer, which then can be transferred by the USB engine. This 
pointer can be any pointer except NULL.

3) As per my knowledge, using busdma to allocate a separate buffer for a 13-
byte buffer, results in having a buffer of PAGE_SIZE bytes allocated.

4) BUSDMA experts: Please verify that the flags passed to bus_dmamap_sync() 
causes the exact behaviour has listed on top of this e-mail to occur in the 
following two functions in sys/dev/usb/usb_busdma.c

void
usb_pc_cpu_invalidate(struct usb_page_cache *pc)
{
        if (pc->page_offset_end == pc->page_offset_buf) {
                /* nothing has been loaded into this page cache! */
                return;
        }

        /*
         * TODO: We currently do XXX_POSTREAD and XXX_PREREAD at the
         * same time, but in the future we should try to isolate the
         * different cases to optimise the code. --HPS
         */
        bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_POSTREAD);
        bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_PREREAD);
}

void
usb_pc_cpu_flush(struct usb_page_cache *pc)
{
        if (pc->page_offset_end == pc->page_offset_buf) {
                /* nothing has been loaded into this page cache! */
                return;
        }
        bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_PREWRITE);
}

--HPS



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201212190956.28609.hselasky>