This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM3354: Ethernet receive problem

Part Number: AM3354

Hi,

We are having Am335x processor based product and we are using starter-ware for the Software. We are using Ethernet interface.

After booting Ethernet interface is initialized, link is established and we are able to receive and transmit packets. But after some duration Ethernet interface is not working properly. We are not able to receive packets.

We debugged and found out that we are not  receiving Ethernet 'rx interrupt'.

In TRM, they mentioned following

"Write the 3PSW completion pointer(s) (RXn_CP). The data written by the host (buffer descriptor address of the last processed buffer) is compared to the data in the register written by the subsystem
(address of last buffer descriptor used by the subsystem). If the two values are not equal (which means that the 3PSW has received more packets than the CPU has processed), the receive packet
completion interrupt signal remains asserted. If the two values are equal (which means that the host has processed all packets that the system has received), the pending interrupt is de-asserted. The
value that the 3PSW is expecting is found by reading the receive channeln completion pointer register (RXn_CP)"

So we checked whether CPPI DMA is processing or not. We checked RXHDP (Head descriptor pointer). Its value is NULL.  So DMA doesn't know where to write receive packets. I also checked the state of descriptors and all the descriptors are owned by DMA. We are not getting in which case it becomes NULL.

We are am335x starter ware code. We are using same RX interrupt handler logic given in "enet echo" application. It is written according to the software description "Receive operation" given in  TRM.

So we are not able to understand why the RXHDP descriptor is becoming NULL? How can we debug this problem?

 

  • We have the same problem.we have read the all registers value of CPSW with tools ,and compare the value with the working CPSW.
  • Hi Uma,

    As announced here - www.ti.com/.../STARTERWARE-SITARA: TI has completed development of StarterWare for Sitara. TI no longer plans to make updates to this software for bug fixes or future enhancements. AM335x customers – Processor SDK-RTOS is the recommended alternative for StarterWare. The Processor SDK includes demos and benchmarks, and makes code migration easier across TI processors.

    The CPSW EMAC examples are availble from Processor SDK for AM335x at software-dl.ti.com/.../index_FDS.html, see:
    processors.wiki.ti.com/.../Processor_SDK_RTOS_EMAC
    processors.wiki.ti.com/.../Processor_SDK_RTOS_NDK

    Regards,Garrett
  • Hi,

    Thanks for replying, but I am unable to understand how can we resolve out the problem by comparing the values. Which values we have to look out specifically?

    Regards

    Raja

  • We have the same Ethernet receive problem in the linux system ,the  version is linux 3.14.26 for TI SDK.We look the register of CPSW,find the RX0_CP is NULL(0000).We can send the packets ,but can not receive the packet,how can we do to deal with the problem?

  • Hi,
    Which TI SDK release you were referring to? Have you tried the latest Processor SDK Linux - www.ti.com/.../PROCESSOR-SDK-AM335X ?

    Regards,
    Garrett
  • Hi,
    We used the TI SDK release --software-dl.ti.com/.../index_FDS.html.
    We have finished many softwares development work based on the linux kernel 3.14.26 from TI SDK, so it is hardful for us to use the latest Processor SDK Linux with linux 4.9 kernel.
    We want to know the reasons that make the Ethernet receive problem ,likely that After booting Ethernet interface is initialized, link is established and we are able to receive and transmit packets. But after some duration Ethernet interface is not working properly. We are not able to receive packets.
    And RX0_CP is NULL(0000).
    Can we deal with the probles without to try the latest Processor SDK Linux,only by with modify the CPSW driver code of linux 3.14.26 from PROCESSOR-SDK-LINUX-AM335X/01_00_00_00/index_FDS.html.

    Regards,
    Mr GAO
  • Hello Garrett,

    Thanks for replying. Sir, whether the SDK is starterware or RTOS, the Ethernet receive operation should be written according to the steps given in the TRM 14.4.2 Receive operation.

    http://www.ti.com/lit/ug/spruh73p/spruh73p.pdf

    We are following the  steps  given in TRM 14.4.2 "software  receive operation". But still the RXHDP is becoming 'NULL".

    While debugging it looks like abrupt behavior of CPPI DMA. After processing one descriptor from the queue, instead of processing another descriptor, it is updating RXHDP to "NULL", but the queue is not empty, it contains descriptors with buffer information which are owned by DMA and also the descriptors are linked properly..

    I want to know why i am get getting this problem even if we are following the software steps given in TRM

    Thanks

    Raja 

  • Hi,

    There are two different OSs in this thread, I will try to answer them both but I primarily support Linux. The Linux  user may need to file a new thread. For user4238200 is it possible to move to a later SDK and kernel?

    Attached is a Linux patch that changes the cpdma.c file with how the CPDMA pointers are managed. The accessor functions needed to be changed due to the speed of how the internal SOC interconnect was handling the pointer updates. For the Starterware user please review if this method is different than what is in the current driver.

    Regards,

    Schuyler

    From a4e50455d7725c40f547b1395333cd923067f2f2 Mon Sep 17 00:00:00 2001
    From: Grygorii Strashko <grygorii.strashko@ti.com>
    Date: Thu, 1 Sep 2016 20:37:07 +0300
    Subject: [PATCH v2 1/7] net: ethernet: ti: cpdma: am437x: allow descs to be
     plased in ddr
    
    It's observed that cpsw/cpdma is not working properly when CPPI
    descriptors are placed in DDR instead of internal CPPI RAM on am437x
    SoC:
    - rx/tx silently stops processing packets;
    - or - after boot it's working for sometime, but stuck once Network
    load is increased (ping is working, but iperf is not).
    (The same issue has not been reproduced on am335x and am57xx).
    
    It seems that write to HDP register processed faster by interconnect
    than writing of descriptor memory buffer in DDR, which is probably
    caused by store buffer / write buffer differences as these functions
    are implemented differently across devices. So, to fix this i come up
    with two minimal, required changes:
    
    1) all accesses to the channel register HDP/CP/RXFREE registers should
    be done using sync IO accessors readl()/writel(), because all previous
    memory writes writes have to be completed before starting channel
    (write to HDP) or completing desc processing.
    
    2) the change 1 only doesn't work on am437x and additional reading of
    desc's field is required right after the new descriptor was filled
    with data and before pointer on it will be stored in
    prev_desc->hw_next field or HDP register.
    
    In addition, to above changes this patch eliminates all relaxed ordering
    I/O accessors in this driver as suggested by David Miller to avoid such
    kind of issues in the future, but with one exception - relaxed IO accessors
    will still be used to fill desc in cpdma_chan_submit(), which is safe as
    there is read barrier at the end of write sequence, and because sync IO
    accessors usage here will affect on net performance.
    
    Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
    ---
     drivers/net/ethernet/ti/davinci_cpdma.c | 40 ++++++++++++++++++---------------
     1 file changed, 22 insertions(+), 18 deletions(-)
    
    diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
    index 36518fc..d6f0ded 100644
    --- a/drivers/net/ethernet/ti/davinci_cpdma.c
    +++ b/drivers/net/ethernet/ti/davinci_cpdma.c
    @@ -166,12 +166,12 @@ static struct cpdma_control_info controls[] = {
     #define num_chan	params.num_chan
     
     /* various accessors */
    -#define dma_reg_read(ctlr, ofs)		__raw_readl((ctlr)->dmaregs + (ofs))
    -#define chan_read(chan, fld)		__raw_readl((chan)->fld)
    -#define desc_read(desc, fld)		__raw_readl(&(desc)->fld)
    -#define dma_reg_write(ctlr, ofs, v)	__raw_writel(v, (ctlr)->dmaregs + (ofs))
    -#define chan_write(chan, fld, v)	__raw_writel(v, (chan)->fld)
    -#define desc_write(desc, fld, v)	__raw_writel((u32)(v), &(desc)->fld)
    +#define dma_reg_read(ctlr, ofs)		readl((ctlr)->dmaregs + (ofs))
    +#define chan_read(chan, fld)		readl((chan)->fld)
    +#define desc_read(desc, fld)		readl(&(desc)->fld)
    +#define dma_reg_write(ctlr, ofs, v)	writel(v, (ctlr)->dmaregs + (ofs))
    +#define chan_write(chan, fld, v)	writel(v, (chan)->fld)
    +#define desc_write(desc, fld, v)	writel((u32)(v), &(desc)->fld)
     
     #define cpdma_desc_to_port(chan, mode, directed)			\
     	do {								\
    @@ -542,10 +542,10 @@ int cpdma_ctlr_start(struct cpdma_ctlr *ctlr)
     	}
     
     	for (i = 0; i < ctlr->num_chan; i++) {
    -		__raw_writel(0, ctlr->params.txhdp + 4 * i);
    -		__raw_writel(0, ctlr->params.rxhdp + 4 * i);
    -		__raw_writel(0, ctlr->params.txcp + 4 * i);
    -		__raw_writel(0, ctlr->params.rxcp + 4 * i);
    +		writel(0, ctlr->params.txhdp + 4 * i);
    +		writel(0, ctlr->params.rxhdp + 4 * i);
    +		writel(0, ctlr->params.txcp + 4 * i);
    +		writel(0, ctlr->params.rxcp + 4 * i);
     	}
     
     	dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff);
    @@ -1061,13 +1061,17 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
     	mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
     	cpdma_desc_to_port(chan, mode, directed);
     
    -	desc_write(desc, hw_next,   0);
    -	desc_write(desc, hw_buffer, buffer);
    -	desc_write(desc, hw_len,    len);
    -	desc_write(desc, hw_mode,   mode | len);
    -	desc_write(desc, sw_token,  token);
    -	desc_write(desc, sw_buffer, buffer);
    -	desc_write(desc, sw_len,    len);
    +	/* Relaxed IO accessors can be used here as there is read barrier
    +	 * at the end of write sequence.
    +	 */
    +	writel_relaxed(0, &desc->hw_next);
    +	writel_relaxed(buffer, &desc->hw_buffer);
    +	writel_relaxed(len, &desc->hw_len);
    +	writel_relaxed(mode | len, &desc->hw_mode);
    +	writel_relaxed(token, &desc->sw_token);
    +	writel_relaxed(buffer, &desc->sw_buffer);
    +	writel_relaxed(len, &desc->sw_len);
    +	desc_read(desc, sw_len);
     
     	__cpdma_chan_submit(chan, desc);
     
    @@ -1136,7 +1140,7 @@ static int __cpdma_chan_process(struct cpdma_chan *chan)
     	}
     	desc_dma = desc_phys(pool, desc);
     
    -	status	= __raw_readl(&desc->hw_mode);
    +	status	= desc_read(desc, hw_mode);
     	outlen	= status & 0x7ff;
     	if (status & CPDMA_DESC_OWNER) {
     		chan->stats.busy_dequeue++;
    -- 
    2.10.1.dirty
    
    

  • Hello Schuyler

    In our case we are not using external memory for CPPI descriptors, we are using CPPI DMA descriptors memory.

    Regards

    Raja
  • To user4238200:

    You are stealing other people's thread. Please open your own thread for any questions you have. Your questions will not be answered on this current thread.
  • Hello Schuyler

    I tested the Ethernet functionality using "DSB" assembly instruction before and after descriptors updates. In that case also it is failing i.e RXHDP is becoming NULL after some time.

    Please guide me in resolving the problem

    Regards

    Raja
  • Hi,

    In AM335x can we use external memory i.e RAM for Tx and Rx buffer descriptors instead of CPPI RAM (8KBytes) memory?

    Regards

    Raja
  • Raja,

    Yes, you can use the external memory for buffer descriptor in AM335x, see the comment in the patch from Schuyler:

    It's observed that cpsw/cpdma is not working properly when CPPI

    descriptors are placed in DDR instead of internal CPPI RAM on am437x

    SoC:

    - rx/tx silently stops processing packets;

    - or - after boot it's working for sometime, but stuck once Network

    load is increased (ping is working, but iperf is not).

    (The same issue has not been reproduced on am335x and am57xx).

    Regards,

    Garrett

  • Raja/Uma,

    For RXHDP null issue you observed with Starterware, you may refer to the implementation of emac_cpsw.c in PDK driver that have been verified on Sitara processors.

    Some relevant functions are:
    * @n@b EMAC_enqueueRx()
    * @n Fill any empty RX descriptors with new buffers from the application

    * @n@b EMAC_dequeueRx()
    * @n Dequeue all completed RX packets and give buffers to application

    * @n@b EMAC_cpswInitRxChannel()
    * @n This function sets up the Receive Buffer descriptors.

    Note there is cache invalidation prior to pushing the packet buffer on the local descriptor queue.
    EMAC_osalCacheInv((void*)pPkt->pDataBuffer, pPkt->BufferLen);
    EMAC_pqPush(&pdc->DescQueue, pPkt);

    Regards,
    Garrett