[PR 18 v2] GRETH: added support for non-snooping GRETH 10/100 systems

Daniel Hellstrom daniel at gaisler.com
Wed Feb 8 15:33:24 UTC 2012


On 02/08/2012 04:27 PM, Gedare Bloom wrote:
> I have just some small nits.
Ok, I will update to uintptr_t and create a new PR with the patch once bugzilla is working again.

Daniel

> 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