diff --git a/c/src/lib/libbsp/powerpc/beatnik/ChangeLog b/c/src/lib/libbsp/powerpc/beatnik/ChangeLog index eb768cb15b..e8dd64c9ea 100644 --- a/c/src/lib/libbsp/powerpc/beatnik/ChangeLog +++ b/c/src/lib/libbsp/powerpc/beatnik/ChangeLog @@ -1,3 +1,21 @@ +2010-02-09 Till Straumann + + * network/if_mve/mv643xx_eth.c: Fixed alignment attribute + in descriptor declaration. Not the pointers to the descriptors + have to be aligned but the descriptors themselves (didn't + cause problems but caused unnecessary holes in 'private' struct). + + FIX: Added more robustness when number of available TX descriptors + drops to zero. (This can e.g., happen if the link goes bad causing + packets to stall in the FIFO.) At the following points the transmitter + is explicitly (re-)started: + o when link comes up and number of available TXDs is zero the + TX is restarted. + o on a failed attempt to send data due to lack of TXDs the + TX is restarted if swiping the TX ring doesn't yield any + buffers (i.e., if the # of available buffers is still zero + after the swipe). + 2009-12-14 Sebastian Huber * Makefile.am, preinstall.am: Removed ppc_exc_bspsupp.h include file. diff --git a/c/src/lib/libbsp/powerpc/beatnik/network/if_mve/mv643xx_eth.c b/c/src/lib/libbsp/powerpc/beatnik/network/if_mve/mv643xx_eth.c index e9e1779574..812961ebc2 100644 --- a/c/src/lib/libbsp/powerpc/beatnik/network/if_mve/mv643xx_eth.c +++ b/c/src/lib/libbsp/powerpc/beatnik/network/if_mve/mv643xx_eth.c @@ -687,8 +687,7 @@ typedef volatile struct mveth_rx_desc { void *u_buf; /* user buffer */ volatile struct mveth_rx_desc *next; /* next descriptor (CPU address; next_desc_ptr is a DMA address) */ uint32_t pad[2]; -} MvEthRxDescRec, *MvEthRxDesc -__attribute__(( aligned(RING_ALIGNMENT) )); +} __attribute__(( aligned(RING_ALIGNMENT) )) MvEthRxDescRec, *MvEthRxDesc; typedef volatile struct mveth_tx_desc { #ifndef __BIG_ENDIAN__ @@ -703,8 +702,7 @@ typedef volatile struct mveth_tx_desc { uint32_t workaround[2]; /* use this space to work around the 8byte problem (is this real?) */ void *u_buf; /* user buffer */ volatile struct mveth_tx_desc *next; /* next descriptor (CPU address; next_desc_ptr is a DMA address) */ -} MvEthTxDescRec, *MvEthTxDesc -__attribute__(( aligned(RING_ALIGNMENT) )); +} __attribute__(( aligned(RING_ALIGNMENT) )) MvEthTxDescRec, *MvEthTxDesc; /* Assume there are never more then 64k aliasing entries */ typedef uint16_t Mc_Refcnt[MV643XX_ETH_NUM_MCAST_ENTRIES*4]; @@ -1222,6 +1220,19 @@ unsigned wc = 0; /* MID-LAYER SUPPORT ROUTINES */ +/* Start TX if descriptors are exhausted */ +static __inline__ void +mveth_start_tx(struct mveth_private *mp) +{ +uint32_t running; + if ( mp->avail <= 0 ) { + running = MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_R(mp->port_num)); + if ( ! (running & MV643XX_ETH_TX_START(0)) ) { + MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_R(mp->port_num), MV643XX_ETH_TX_START(0)); + } + } +} + /* Stop TX and wait for the command queues to stop and the fifo to drain */ static uint32_t mveth_stop_tx(int port) @@ -1955,6 +1966,8 @@ startover: /* if no descriptor is available; try to wipe the queue */ if ( (mp->avail < 1) && MVETH_CLEAN_ON_SEND(mp)<=0 ) { + /* Maybe TX is stalled and needs to be restarted */ + mveth_start_tx(mp); return -1; } @@ -2000,6 +2013,9 @@ startover: nmbs++; if ( mp->avail < 1 && MVETH_CLEAN_ON_SEND(mp)<=0 ) { + /* Maybe TX was stalled - try to restart */ + mveth_start_tx(mp); + /* not enough descriptors; cleanup... * the first slot was never used, so we start * at mp->d_tx_h->next; @@ -2142,6 +2158,8 @@ int frst_len; /* if no descriptor is available; try to wipe the queue */ if ( ( mp->avail < needed ) && ( MVETH_CLEAN_ON_SEND(mp) <= 0 || mp->avail < needed ) ) { + /* Maybe TX was stalled and needs a restart */ + mveth_start_tx(mp); return -1; } @@ -2606,6 +2624,8 @@ int media = IFM_MAKEWORD(0,0,0,0); if ( 0 == BSP_mve_media_ioctl(mp, SIOCGIFMEDIA, &media)) { if ( IFM_LINK_OK & media ) { mveth_update_serial_port(mp, media); + /* If TX stalled because there was no buffer then whack it */ + mveth_start_tx(mp); } if ( pmedia ) *pmedia = media;