Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/marvell Fix device timeout problem.
details: https://anonhg.NetBSD.org/src/rev/609ff59856cb
branches: trunk
changeset: 781661:609ff59856cb
user: msaitoh <msaitoh%NetBSD.org@localhost>
date: Fri Sep 21 00:26:15 2012 +0000
description:
Fix device timeout problem.
- Change the synching order of descriptors. First, sync descriptors except
first and then sync the first descriptor.
- To recover from an race condition, reduce the if_timer from 5 to 1 and
when timeout occur write MVGBE_TQC_ENQ bit again.
diffstat:
sys/dev/marvell/if_mvgbe.c | 42 +++++++++++++++++++++++++++++++-----------
1 files changed, 31 insertions(+), 11 deletions(-)
diffs (113 lines):
diff -r 3deecea1adef -r 609ff59856cb sys/dev/marvell/if_mvgbe.c
--- a/sys/dev/marvell/if_mvgbe.c Thu Sep 20 23:50:05 2012 +0000
+++ b/sys/dev/marvell/if_mvgbe.c Fri Sep 21 00:26:15 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_mvgbe.c,v 1.19 2012/09/06 03:45:02 msaitoh Exp $ */
+/* $NetBSD: if_mvgbe.c,v 1.20 2012/09/21 00:26:15 msaitoh Exp $ */
/*
* Copyright (c) 2007, 2008 KIYOHARA Takashi
* All rights reserved.
@@ -25,7 +25,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_mvgbe.c,v 1.19 2012/09/06 03:45:02 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_mvgbe.c,v 1.20 2012/09/21 00:26:15 msaitoh Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -206,6 +206,7 @@
struct mvgbe_ring_data *sc_rdata;
bus_dmamap_t sc_ring_map;
int sc_if_flags;
+ int sc_wdogsoft;
LIST_HEAD(__mvgbe_jfreehead, mvgbe_jpool_entry) sc_jfree_listhead;
LIST_HEAD(__mvgbe_jinusehead, mvgbe_jpool_entry) sc_jinuse_listhead;
@@ -903,7 +904,8 @@
/*
* Set a timeout in case the chip goes out to lunch.
*/
- ifp->if_timer = 5;
+ ifp->if_timer = 1;
+ sc->sc_wdogsoft = 1;
}
}
@@ -1162,11 +1164,22 @@
*/
mvgbe_txeof(sc);
if (sc->sc_cdata.mvgbe_tx_cnt != 0) {
- aprint_error_ifnet(ifp, "watchdog timeout\n");
+ if (sc->sc_wdogsoft) {
+ /*
+ * There is race condition between CPU and DMA
+ * engine. When DMA engine encounters queue end,
+ * it clears MVGBE_TQC_ENQ bit.
+ */
+ MVGBE_WRITE(sc, MVGBE_TQC, MVGBE_TQC_ENQ);
+ ifp->if_timer = 5;
+ sc->sc_wdogsoft = 0;
+ } else {
+ aprint_error_ifnet(ifp, "watchdog timeout\n");
- ifp->if_oerrors++;
+ ifp->if_oerrors++;
- mvgbe_init(ifp);
+ mvgbe_init(ifp);
+ }
}
}
@@ -1589,7 +1602,8 @@
f = &sc->sc_rdata->mvgbe_tx_ring[current];
f->bufptr = txseg[i].ds_addr;
f->bytecnt = txseg[i].ds_len;
- f->cmdsts = MVGBE_BUFFER_OWNED_BY_DMA;
+ if (i != 0)
+ f->cmdsts = MVGBE_BUFFER_OWNED_BY_DMA;
last = current;
current = MVGBE_TX_RING_NEXT(current);
}
@@ -1610,7 +1624,6 @@
}
if (txmap->dm_nsegs == 1)
f->cmdsts = cmdsts |
- MVGBE_BUFFER_OWNED_BY_DMA |
MVGBE_TX_GENERATE_CRC |
MVGBE_TX_ENABLE_INTERRUPT |
MVGBE_TX_ZERO_PADDING |
@@ -1619,7 +1632,6 @@
else {
f = &sc->sc_rdata->mvgbe_tx_ring[first];
f->cmdsts = cmdsts |
- MVGBE_BUFFER_OWNED_BY_DMA |
MVGBE_TX_GENERATE_CRC |
MVGBE_TX_FIRST_DESC;
@@ -1629,14 +1641,22 @@
MVGBE_TX_ENABLE_INTERRUPT |
MVGBE_TX_ZERO_PADDING |
MVGBE_TX_LAST_DESC;
+
+ /* Sync descriptors except first */
+ MVGBE_CDTXSYNC(sc,
+ (MVGBE_TX_RING_CNT - 1 == *txidx) ? 0 : (*txidx) + 1,
+ txmap->dm_nsegs - 1,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
}
sc->sc_cdata.mvgbe_tx_chain[last].mvgbe_mbuf = m_head;
SIMPLEQ_REMOVE_HEAD(&sc->sc_txmap_head, link);
sc->sc_cdata.mvgbe_tx_map[last] = entry;
- /* Sync descriptors before handing to chip */
- MVGBE_CDTXSYNC(sc, *txidx, txmap->dm_nsegs,
+ /* Finally, sync first descriptor */
+ sc->sc_rdata->mvgbe_tx_ring[first].cmdsts |=
+ MVGBE_BUFFER_OWNED_BY_DMA;
+ MVGBE_CDTXSYNC(sc, *txidx, 1,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
sc->sc_cdata.mvgbe_tx_cnt += i;
Home |
Main Index |
Thread Index |
Old Index