[PR 18] GRETH: added support for non-snooping GRETH 10/100 systems
Gedare Bloom
gedare at rtems.org
Mon Feb 6 16:32:36 UTC 2012
On Mon, Feb 6, 2012 at 9:15 AM, Daniel Hellstrom <daniel at gaisler.com> wrote:
> When data cache snooping is not present the cache needs
> flushing, the SPARC LEON CPUs does not have to ability
> to flush individual cache rows and flushing all cache is
> expensive. Instead the LDA instruction is used to force
> cache miss on individual loads during the IP-align copy
> operation required anyway.
>
> GRETH GBIT non-snooping systems are still unsupported,
> since it use zero-copy (can deal with unaligned DMA).
>
> Also, made the GRETH driver only built on LEON2/LEON3
> platforms.
>
> Signed-off-by: Daniel Hellstrom <daniel at gaisler.com>
> ---
> c/src/libchip/network/greth.c | 80 +++++++++++++++++++++++++++++++++++++---
> 1 files changed, 74 insertions(+), 6 deletions(-)
>
> diff --git a/c/src/libchip/network/greth.c b/c/src/libchip/network/greth.c
> index b0e70b4..6af5283 100644
> --- a/c/src/libchip/network/greth.c
> +++ b/c/src/libchip/network/greth.c
> @@ -12,10 +12,15 @@
> */
>
> #include <rtems.h>
> -
> -#define GRETH_SUPPORTED
> #include <bsp.h>
>
> +/* This driver is only supported by the LEON BSPs */
> +#if defined(LEON3) || defined(LEON2)
> + #define GRETH_SUPPORTED
> +#endif
> +
> +#ifdef GRETH_SUPPORTED
> +
> #include <inttypes.h>
> #include <errno.h>
> #include <rtems/bspIo.h>
> @@ -57,6 +62,14 @@ extern rtems_isr_entry set_vector( rtems_isr_entry, rtems_vector_number, int );
> extern void ipalign(struct mbuf *m);
> #endif
>
> +static inline unsigned int sparc_load_no_cache(unsigned int addr)
> +{
> + unsigned int tmp;
> + asm volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(addr) );
> + return tmp;
> +}
> +#define NO_CACHE_LOAD(addr) sparc_load_no_cache(addr)
> +
> /*
> * Number of OCs supported by this driver
> */
> @@ -499,6 +512,47 @@ auto_neg_done:
> print_init_info(sc);
> }
>
> +#ifdef CPU_U32_FIX
> +
> +/*
> + * Routine to align the received packet so that the ip header
> + * is on a 32-bit boundary. Necessary for cpu's that do not
> + * allow unaligned loads and stores and when the 32-bit DMA
> + * mode is used.
> + *
> + * Transfers are done on word basis to avoid possibly slow byte
> + * and half-word writes.
> + */
> +
> +void ipalign(struct mbuf *m)
> +{
> + unsigned int *first, *last, data;
> + unsigned int tmp = 0;
> +
> + if ((((int) m->m_data) & 2) && (m->m_len)) {
> + last = (unsigned int *) ((((int) m->m_data) + m->m_len + 8) & ~3);
> + first = (unsigned int *) (((int) m->m_data) & ~3);
We should really have some generic alignment macros to make reading
this type of code easier..
> + /* tmp = *first << 16; */
Delete this line if it is unnecessary comment.
> + asm volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(first) );
Fix whitespace, and can we use here the inline function?
tmp = NO_CACHE_LOAD(first)
> + tmp = tmp << 16;
> + first++;
> + do {
> + /* When snooping is not available the LDA instruction must be used
> + * to avoid the cache to return an illegal value.
> + * Load with forced cache miss
> + * data = *first;
> + */
> + asm volatile (" lda [%1] 1, %0\n" : "=r"(data) : "r"(first) );
Can use here? data = NO_CACHE_LOAD(first)
> + *first = tmp | (data >> 16);
> + tmp = data << 16;
> + first++;
> + } while (first <= last);
> +
> + m->m_data = (caddr_t)(((int) m->m_data) + 2);
> + }
> +}
> +#endif
> +
> void
> greth_Daemon (void *arg)
> {
> @@ -510,6 +564,8 @@ greth_Daemon (void *arg)
> rtems_event_set events;
> rtems_interrupt_level level;
> int first;
> + int tmp;
tmp probably should be unsigned int (just for type matching); though
the variable may be unnecessary if the NO_CACHE_LOAD macro/inline
function is used.
> + unsigned int addr;
addr probably should have type uintptr_t.
>
> for (;;)
> {
> @@ -539,7 +595,7 @@ greth_Daemon (void *arg)
> /* Scan for Received packets */
> again:
> while (!((len_status =
> - dp->rxdesc[dp->rx_ptr].ctrl) & GRETH_RXD_ENABLE))
> + NO_CACHE_LOAD(&dp->rxdesc[dp->rx_ptr].ctrl)) & GRETH_RXD_ENABLE))
> {
> bad = 0;
> if (len_status & GRETH_RXD_TOOLONG)
> @@ -583,6 +639,17 @@ again:
> len - sizeof (struct ether_header);
>
> eh = mtod (m, struct ether_header *);
> +
> + /* OVERRIDE CACHED ETHERNET HEADER FOR NON-SNOOPING SYSTEMS */
> + addr = (unsigned int)eh;
cast to uintptr_t
> + asm volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(addr) );
> + addr+=4;
> + asm volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(addr) );
> + addr+=4;
> + asm volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(addr) );
> + addr+=4;
> + asm volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(addr) );
> +
Can we use here:
NO_CACHE_LOAD(addr);
NO_CACHE_LOAD(addr+4);
NO_CACHE_LOAD(addr+8);
NO_CACHE_LOAD(addr+12);
addr +=12 (if necessary for correctness....)
> m->m_data += sizeof (struct ether_header);
> #ifdef CPU_U32_FIX
> if(!(dp->gbit_mac))
> @@ -641,7 +708,7 @@ sendpacket (struct ifnet *ifp, struct mbuf *m)
> /*
> * Is there a free descriptor available?
> */
> - if ( dp->txdesc[dp->tx_ptr].ctrl & GRETH_TXD_ENABLE ){
> + if ( NO_CACHE_LOAD(&dp->txdesc[dp->tx_ptr].ctrl) & GRETH_TXD_ENABLE ){
> /* No. */
> inside = 0;
> return 1;
> @@ -651,7 +718,7 @@ sendpacket (struct ifnet *ifp, struct mbuf *m)
> n = m;
>
> len = 0;
> - temp = (unsigned char *) dp->txdesc[dp->tx_ptr].addr;
> + temp = (unsigned char *) NO_CACHE_LOAD(&dp->txdesc[dp->tx_ptr].addr);
> #ifdef GRETH_DEBUG
> printf("TXD: 0x%08x : BUF: 0x%08x\n", (int) m->m_data, (int) temp);
> #endif
> @@ -814,7 +881,7 @@ int greth_process_tx_gbit(struct greth_softc *sc)
> */
> for (;;){
> /* Reap Sent packets */
> - while((sc->tx_cnt > 0) && !(sc->txdesc[sc->tx_dptr].ctrl) && !(sc->txdesc[sc->tx_dptr].ctrl & GRETH_TXD_ENABLE)) {
> + while((sc->tx_cnt > 0) && !(NO_CACHE_LOAD(&sc->txdesc[sc->tx_dptr].ctrl) & GRETH_TXD_ENABLE)) {
> m_free(sc->txmbuf[sc->tx_dptr]);
> sc->tx_dptr = (sc->tx_dptr + 1) % sc->txbufs;
> sc->tx_cnt--;
> @@ -1146,3 +1213,4 @@ rtems_greth_driver_attach (struct rtems_bsdnet_ifconfig *config,
> return 1;
> };
>
> +#endif
> --
> 1.7.0.4
>
> _______________________________________________
> rtems-devel mailing list
> rtems-devel at rtems.org
> http://www.rtems.org/mailman/listinfo/rtems-devel
More information about the devel
mailing list