[PR 18 v2] GRETH: added support for non-snooping GRETH 10/100 systems
Gedare Bloom
gedare at rtems.org
Wed Feb 8 15:27:16 UTC 2012
I have just some small nits.
On Wed, Feb 8, 2012 at 9:57 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 | 73 +++++++++++++++++++++++++++++++++++++---
> 1 files changed, 67 insertions(+), 6 deletions(-)
>
> diff --git a/c/src/libchip/network/greth.c b/c/src/libchip/network/greth.c
> index b0e70b4..628fe77 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)
addr probably should have type uintptr_t; not a big deal since on all
sparc32/leon cores uint and uintptr_t are the same.
> +{
> + 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)
> +
I did not notice before, but this use of assembly in a network driver
is a little unorthodox. I realize though this network driver is only
meant for leon cores so maybe it is OK. If someone else has a problem
with it, there are ways to get around it (e.g. by moving
sparc_load_no_cache function to somewhere sensible like
cpukit/score/cpu/sparc/rtems/score/sparc.h).
> /*
> * Number of OCs supported by this driver
> */
> @@ -499,6 +512,45 @@ 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;
> +
> + 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);
> + 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 = 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 +562,7 @@ greth_Daemon (void *arg)
> rtems_event_set events;
> rtems_interrupt_level level;
> int first;
> + unsigned int tmp;
>
> for (;;)
> {
> @@ -539,7 +592,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 +636,13 @@ again:
> len - sizeof (struct ether_header);
>
> eh = mtod (m, struct ether_header *);
> +
> + /* OVERRIDE CACHED ETHERNET HEADER FOR NON-SNOOPING SYSTEMS */
> + tmp = NO_CACHE_LOAD((unsigned int)eh);
> + tmp = NO_CACHE_LOAD(4 + (unsigned int)eh);
> + tmp = NO_CACHE_LOAD(8 + (unsigned int)eh);
> + tmp = NO_CACHE_LOAD(12 + (unsigned int)eh);
cast eh to uintptr_t.
> +
> m->m_data += sizeof (struct ether_header);
> #ifdef CPU_U32_FIX
> if(!(dp->gbit_mac))
> @@ -641,7 +701,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 +711,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 +874,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 +1206,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