From f30add70f8718383332e44d9f92fe2534ac4424a Mon Sep 17 00:00:00 2001 From: Grzegorz Daniluk <grzegorz.daniluk@cern.ch> Date: Tue, 28 Aug 2012 17:03:03 +0200 Subject: [PATCH] dev/minic: bugfixes to prevent WRPC from hanging on ping flood --- dev/minic.c | 65 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/dev/minic.c b/dev/minic.c index 6b9e52f..2c82aeb 100644 --- a/dev/minic.c +++ b/dev/minic.c @@ -62,46 +62,53 @@ static inline uint32_t minic_readl(uint32_t reg) return *(volatile uint32_t *)(BASE_MINIC + reg); } +/* + * uint32_t size - in bytes + */ static uint8_t * minic_rx_memcpy( uint8_t *dst, uint8_t *src, uint32_t size) { uint32_t part; //if src is outside the circular buffer, bring it back to the beginning - src = (uint8_t *) ((uint32_t)minic.rx_base + ((uint32_t)src - (uint32_t)minic.rx_base) % minic.rx_size); + src = (uint8_t *) ((uint32_t)minic.rx_base + ((uint32_t)src - (uint32_t)minic.rx_base) % (minic.rx_size<<2)); - if((uint32_t)src + size <= (uint32_t)minic.rx_base + minic.rx_size) + if((uint32_t)src + size <= (uint32_t)minic.rx_base + (minic.rx_size<<2)) return memcpy(dst, src, size); - part = (uint32_t)minic.rx_base + minic.rx_size - (uint32_t)src; + part = (uint32_t)minic.rx_base + (minic.rx_size<<2) - (uint32_t)src; memcpy(dst, src, part); memcpy((void*) (dst+part), (void*)minic.rx_base, size - part); return dst; } +/* + * uint32_t size - in bytes + */ static uint8_t *minic_rx_memset( uint8_t *mem, uint8_t c, uint32_t size) { uint32_t part; - uint8_t *src; + uint32_t *src; //if src is outside the circular buffer, bring it back to the beginning - src = (uint8_t *) ((uint32_t)minic.rx_base + ((uint32_t)mem - (uint32_t)minic.rx_base) % minic.rx_size); + src = (uint32_t*)((uint32_t)minic.rx_base + ((uint32_t)mem - (uint32_t)minic.rx_base) % (minic.rx_size<<2)); - if((uint32_t)src + size <= (uint32_t)minic.rx_base + minic.rx_size) - return memset(src, c, size); + if((uint32_t)src + size <= (uint32_t)minic.rx_base + (minic.rx_size<<2)) + return memset((void*)src, c, size); - part = (uint32_t)minic.rx_base + minic.rx_size - (uint32_t)src; + part = (uint32_t)minic.rx_base + (minic.rx_size<<2) - (uint32_t)src; memset(src, c, part); memset((void*)minic.rx_base, c, size - part); - return src; + return (uint8_t*)src; } static void minic_new_rx_buffer() { minic_writel(MINIC_REG_MCR, 0); + minic.rx_base = dma_rx_buf; + minic.rx_size = MINIC_DMA_RX_BUF_SIZE/4; minic.rx_head = minic.rx_base; - minic_rx_memset((uint8_t*)minic.rx_base, 0x00, minic.rx_size); - memset((void*)minic.rx_base, 0x0, minic.rx_size); + minic_rx_memset((uint8_t*)minic.rx_base, 0x00, minic.rx_size<<2); minic_writel(MINIC_REG_RX_ADDR, (uint32_t) minic.rx_base); - minic_writel(MINIC_REG_RX_SIZE, minic.rx_size>>2); + minic_writel(MINIC_REG_RX_SIZE, minic.rx_size); //new buffer allocated, clear any old RX interrupts minic_writel(MINIC_REG_EIC_ISR, MINIC_EIC_ISR_RX); minic_writel(MINIC_REG_MCR, MINIC_MCR_RX_EN); @@ -115,8 +122,11 @@ static void minic_rxbuf_free(uint32_t words) static void minic_new_tx_buffer() { + minic.tx_base = dma_tx_buf; + minic.tx_size = MINIC_DMA_TX_BUF_SIZE>>2; + minic.tx_head = minic.tx_base; - minic.tx_avail = minic.tx_size>>2; + minic.tx_avail = minic.tx_size; minic_writel(MINIC_REG_TX_ADDR, (uint32_t) minic.tx_base); } @@ -140,7 +150,7 @@ void minic_init() minic_writel(MINIC_REG_MPROT, MINIC_MPROT_LO_W(lo) | MINIC_MPROT_HI_W(hi)); minic.tx_base = dma_tx_buf; - minic.tx_size = sizeof(dma_tx_buf); + minic.tx_size = MINIC_DMA_TX_BUF_SIZE>>2; minic.tx_count = 0; minic.rx_count = 0; @@ -174,14 +184,19 @@ int minic_rx_frame(uint8_t *hdr, uint8_t *payload, uint32_t buf_size, struct hw_ if(! (minic_readl(MINIC_REG_EIC_ISR) & MINIC_EIC_ISR_RX)) return 0; - //TRACE_DEV("minic: got sthx \n"); - desc_hdr = *minic.rx_head; if(!RX_DESC_VALID(desc_hdr)) /* invalid descriptor? Weird, the RX_ADDR seems to be saying something different. Ignore the packet and purge the RX buffer. */ { - mprintf("invalid descriptor\n"); - minic_new_rx_buffer(); + //invalid descriptor ? then probably the interrupt was generated by full rx buffer + if(minic_readl(MINIC_REG_MCR) & MINIC_MCR_RX_FULL) + minic_new_rx_buffer(); + else + { + //otherwise, weird !! + mprintf("invalid descriptor @%x = %x\n", (uint32_t)minic.rx_head, desc_hdr); + minic_new_rx_buffer(); + } return 0; } payload_size = RX_DESC_SIZE(desc_hdr); @@ -195,7 +210,7 @@ int minic_rx_frame(uint8_t *hdr, uint8_t *payload, uint32_t buf_size, struct hw_ if(RX_DESC_HAS_OOB(desc_hdr) && hwts != NULL) { uint32_t counter_r, counter_f, counter_ppsg; - uint64_t sec; + uint64_t sec; int cntr_diff; uint16_t dhdr; @@ -228,17 +243,17 @@ int minic_rx_frame(uint8_t *hdr, uint8_t *payload, uint32_t buf_size, struct hw_ minic_rx_memcpy(hdr, (void*)minic.rx_head + 4, ETH_HEADER_SIZE); minic_rx_memcpy(payload, (void*)minic.rx_head + 4 + ETH_HEADER_SIZE, n_recvd - ETH_HEADER_SIZE); - - } else { + } + else { n_recvd = -1; } - minic_rxbuf_free(num_words); - minic.rx_head = (uint32_t * ) ((uint32_t)minic.rx_base + ((uint32_t)minic.rx_head+(num_words<<2) - (uint32_t)minic.rx_base) % minic.rx_size); + minic_rxbuf_free(num_words); + minic.rx_head = (uint32_t *)((uint32_t)minic.rx_base + ((uint32_t)minic.rx_head+(num_words<<2) - (uint32_t)minic.rx_base) % (minic.rx_size<<2)); cur_avail = minic_readl(MINIC_REG_RX_AVAIL); /*empty buffer->no more received packets, or packet reception in progress but not done*/ - if( cur_avail == (minic.rx_size>>2) || !RX_DESC_VALID(*minic.rx_head)) + if( !RX_DESC_VALID(*minic.rx_head)) { if(minic_readl(MINIC_REG_MCR) & MINIC_MCR_RX_FULL) minic_new_rx_buffer(); @@ -258,8 +273,6 @@ int minic_tx_frame(uint8_t *hdr, uint8_t *payload, uint32_t size, struct hw_time uint8_t ts_valid; minic_new_tx_buffer(); - -// TRACE_DEV("minic_tx_frame: head %x size %d\n", minic.tx_head, size); memset((void*)minic.tx_head, 0x0, size + 16); memset((void*)minic.tx_head + 4, 0, size < 60 ? 60 : size); memcpy((void*)minic.tx_head + 4, hdr, ETH_HEADER_SIZE); -- GitLab