Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 8 Jul 2002 15:21:14 -0700
From:      Luigi Rizzo <luigi@FreeBSD.ORG>
To:        Peter Wemm <peter@wemm.org>
Cc:        Don Lewis <dl-freebsd@catspoiler.org>, cvs-committers@FreeBSD.ORG, cvs-all@FreeBSD.ORG
Subject:   Re: cvs commit: src/sys/dev/fxp if_fxp.c
Message-ID:  <20020708152114.K77043@iguana.icir.org>
In-Reply-To: <20020708215808.B34E53808@overcee.wemm.org>; from peter@wemm.org on Mon, Jul 08, 2002 at 02:58:08PM -0700
References:  <20020708145235.I77043@iguana.icir.org> <20020708215808.B34E53808@overcee.wemm.org>

next in thread | previous in thread | raw e-mail | index | archive | help
The intended behaviour of the timeout was to fire if you queue a
packet for transmission and do not get any success report (typically
an interrupt) within some time (typically 5 seconds).

Then a bunch of drivers came out which incorrectly reset the timeout
after the first successful transmission, irrespective of the presence
of other queued packets.  If the card for some reason stalls on one
of these packets, there is no other way (at least as implemented)
to wake it up.

I have been hit myself by this problem with the "dc" and "sis"
drivers -- the problem is sporadical but when it happened it prevented
further transmission on the interface unless some other process did
a *_init() e.g. by bringing the interface down/up or doing some
reconfiguration on it.

I have received reports of the same problem on the "fxp" as well,
though I have not experienced one myself.

Now, one thing that is peculiar about the fxp driver is that it
does not interrupt on every transmission, but only every now and
then. So the timeout might fire when the queue has been drained but
no signal has been posted.

So in this specific driver, it would be more correct to invoke
fxp_intr_body() from the watchdog handler, and check if there are
pending tx packets after that before declaring a real timeout.

In case you want to try it, the following should do:

 static void
 fxp_watchdog(struct ifnet *ifp)
 {
        struct fxp_softc *sc = ifp->if_softc;
+	int s = splimp();

+	fxp_intr_body(sc, FXP_SCB_STATACK_CNA, 0);
+	splx(s);
+	if (sc->tx_queued == 0)
+		return;
+
        device_printf(sc->dev, "device timeout\n");
        ifp->if_oerrors++;

        fxp_init(sc);
 }

I'd be grateful if you could try it.

	cheers
	luigi

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe cvs-all" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020708152114.K77043>