[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