Subject: another if_cnw.c stabilization
To: None <tech-net@netbsd.org>
From: Jun-ichiro itojun Hagino <itojun@iijlab.net>
List: tech-net
Date: 01/22/2000 01:48:49
------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <19496.948473314.1@lychee.itojun.org>
Content-Transfer-Encoding: 7bit
this patch integrates one of stabilization patch from freebsd PAO/bsdi
cnw driver. I'm not sure if it really stabilizes the behavior, so
I'd like to solicit your experience reports. Please let me know if
it works for you, or not.
taken against KAME NetBSD 1.4.1, but should apply fine against
NetBSD-current.
itojun
------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <19496.948473314.2@lychee.itojun.org>
Content-Transfer-Encoding: 7bit
Index: if_cnw.c
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/sys/dev/pcmcia/if_cnw.c,v
retrieving revision 1.2
diff -c -r1.2 if_cnw.c
*** if_cnw.c 1999/11/29 12:23:17 1.2
--- if_cnw.c 2000/01/21 16:42:21
***************
*** 163,168 ****
--- 163,179 ----
#endif
int cnw_skey = CNW_SCRAMBLEKEY; /* Scramble key */
+ /*
+ * The card appears to work much better when we only allow one packet
+ * "in the air" at a time. This is done by not allowing another packet
+ * on the card, even if there is room. Turning this off will allow the
+ * driver to stuff packets on the card as soon as a transmit buffer is
+ * available. This does increase the number of collisions, though.
+ * We can que a second packet if there are transmit buffers available,
+ * but we do not actually send the packet until the last packet has
+ * been written.
+ */
+ #define ONE_AT_A_TIME
int cnw_match __P((struct device *, struct cfdata *, void *));
void cnw_attach __P((struct device *, struct device *, void *));
***************
*** 186,191 ****
--- 197,204 ----
bus_space_tag_t sc_memt; /* ...bus_space tag */
bus_space_handle_t sc_memh; /* ...bus_space handle */
void *sc_ih; /* Interrupt cookie */
+ struct timeval sc_txlast; /* When the last xmit was made */
+ int sc_active; /* Currently xmitting a packet */
};
struct cfattach cnw_ca = {
***************
*** 386,391 ****
--- 399,405 ----
return (EIO);
}
cnw_init(sc);
+ ifp->if_flags &= ~IFF_OACTIVE;
ifp->if_flags |= IFF_RUNNING;
return (0);
}
***************
*** 528,541 ****
--- 542,602 ----
{
struct cnw_softc *sc = ifp->if_softc;
struct mbuf *m0;
+ int lif;
int asr;
+ #ifdef ONE_AT_A_TIME
+ struct timeval now;
+ #endif
#ifdef CNW_DEBUG
if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
printf("%s: cnw_start\n", ifp->if_xname);
+ if (ifp->if_flags & IFF_OACTIVE)
+ printf("%s: cnw_start reentered\n", ifp->if_xname);
#endif
+ ifp->if_flags |= IFF_OACTIVE;
+
for (;;) {
+ #ifdef ONE_AT_A_TIME
+ microtime(&now);
+ now.tv_sec -= sc->sc_txlast.tv_sec;
+ now.tv_usec -= sc->sc_txlast.tv_usec;
+ if (now.tv_usec < 0) {
+ now.tv_usec += 1000000;
+ now.tv_sec--;
+ }
+
+ /*
+ * Don't ship this packet out until the last
+ * packet has left the building.
+ * If we have not tried to send a packet for 1/5
+ * a second then we assume we lost an interrupt,
+ * lets go on and send the next packet anyhow.
+ *
+ * I suppose we could check to see if it is okay
+ * to put additional packets on the card (beyond
+ * the one already waiting to be sent) but I don't
+ * think we would get any improvement in speed as
+ * we should have ample time to put the next packet
+ * on while this one is going out.
+ */
+ if (sc->sc_active && now.tv_sec == 0 && now.tv_usec < 200000)
+ break;
+ #endif
+
+ /* Make sure the link integrity field is on */
+ WAIT_WOC(sc);
+ lif = bus_space_read_1(sc->sc_memt, sc->sc_memh,
+ sc->sc_memoff + CNW_EREG_LIF);
+ if (lif == 0) {
+ #ifdef CNW_DEBUG
+ if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
+ printf("%s: link integrity %d\n", lif);
+ #endif
+ break;
+ }
+
/* Is there any buffer space available on the card? */
WAIT_WOC(sc);
asr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CNW_REG_ASR);
***************
*** 544,557 ****
if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
printf("%s: no buffer space\n", ifp->if_xname);
#endif
! return;
}
sc->sc_stats.nws_tx++;
IF_DEQUEUE(&ifp->if_snd, m0);
if (m0 == 0)
! return;
#if NBPFILTER > 0
if (ifp->if_bpf)
--- 605,618 ----
if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
printf("%s: no buffer space\n", ifp->if_xname);
#endif
! break;
}
sc->sc_stats.nws_tx++;
IF_DEQUEUE(&ifp->if_snd, m0);
if (m0 == 0)
! break;
#if NBPFILTER > 0
if (ifp->if_bpf)
***************
*** 561,569 ****
cnw_transmit(sc, m0);
++ifp->if_opackets;
ifp->if_timer = 3; /* start watchdog timer */
}
- }
/*
* Transmit a packet.
--- 622,634 ----
cnw_transmit(sc, m0);
++ifp->if_opackets;
ifp->if_timer = 3; /* start watchdog timer */
+
+ microtime(&sc->sc_txlast);
+ sc->sc_active = 1;
}
+ ifp->if_flags &= ~IFF_OACTIVE;
+ }
/*
* Transmit a packet.
***************
*** 869,874 ****
--- 934,943 ----
(tser & CNW_TSER_ERROR) |
CNW_TSER_RTRY);
}
+
+ sc->sc_active = 0;
+ ifp->if_flags &= ~IFF_OACTIVE;
+
/* Continue to send packets from the queue */
cnw_start(&sc->sc_ethercom.ec_if);
}
------- =_aaaaaaaaaa0--