Subject: Re: DDB, savecore and awi0
To: Bill Sommerfeld <sommerfeld@orchard.arlington.ma.us>
From: None <itojun@iijlab.net>
List: tech-kern
Date: 11/09/1999 04:11:36
------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <24056.942088204.1@coconut.itojun.org>
Content-Transfer-Encoding: 7bit
>> I had some lockups with awi.c 1.7. When I remove the card
>> I can get out of lockup, but it panic'ed in config_detach()
>> as expected.
>I've seen one or two of these lockups; haven't characterized anything
>which correlates with it; it's probably looping with interrupts
>masked.
Hope this to fix the problem. Problem seem to occur when we can't
keep packets into memory. Works fine for me (but I'm not quite positive
as I haven't experienced lockup with it)
itojun
------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <24056.942088204.2@coconut.itojun.org>
Content-Transfer-Encoding: 7bit
Index: awi.c
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/sys/dev/ic/awi.c,v
retrieving revision 1.5
diff -c -r1.5 awi.c
*** awi.c 1999/11/08 16:06:13 1.5
--- awi.c 1999/11/08 19:05:58
***************
*** 188,193 ****
--- 188,194 ----
void awi_watchdog __P((struct ifnet *));
void awi_start __P((struct ifnet *));
int awi_ioctl __P((struct ifnet *, u_long, caddr_t));
+ static struct mbuf *awi_dump_rxchain1 __P((struct awi_softc *, u_int32_t, int, int, int));
void awi_dump_rxchain __P((struct awi_softc *, char *, u_int32_t *));
void awi_send_frame __P((struct awi_softc *, struct mbuf *));
***************
*** 1194,1199 ****
--- 1195,1267 ----
}
+ static struct mbuf *
+ awi_dump_rxchain1(sc, frame, len, start, drain)
+ struct awi_softc *sc;
+ u_int32_t frame;
+ int len;
+ int start;
+ int drain;
+ {
+ struct mbuf *m, *top, *mlast;
+ u_int8_t junk[100];
+ int nmove;
+ int mlen;
+
+ if (drain)
+ goto drain;
+
+ if ((sc->sc_ifp->if_flags & IFF_DEBUG) != 0)
+ printf("awi_dump_rxchain1(%d)\n", len);
+ top = mlast = NULL;
+ while (len > 0) {
+ if (start) {
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ mlen = MHLEN;
+ } else {
+ MGET(m, M_DONTWAIT, MT_DATA);
+ mlen = MLEN;
+ }
+ if (m == NULL) {
+ m_freem(top);
+ goto drain;
+ }
+ if (top == NULL)
+ top = m;
+ if (len > MINCLSIZE) {
+ MCLGET(m, M_DONTWAIT);
+ if ((m->m_flags & M_EXT) == 0) {
+ m_free(m);
+ m_freem(top);
+ goto drain;
+ }
+ mlen = MCLBYTES;
+ }
+ nmove = min(len, mlen);
+ if ((sc->sc_ifp->if_flags & IFF_DEBUG) != 0)
+ printf("nmove=%d\n", nmove);
+ awi_read_bytes(sc, frame, mtod(m, u_int8_t *), nmove);
+ m->m_len = nmove;
+ len -= nmove;
+
+ if (mlast != NULL)
+ mlast->m_next = m;
+ mlast = m;
+
+ start = 0;
+ }
+
+ return top;
+
+ drain:
+ while (len > 0) {
+ nmove = min(len, sizeof(junk));
+ awi_read_bytes(sc, frame, junk, nmove);
+ len -= nmove;
+ }
+ return NULL;
+ }
+
void
awi_dump_rxchain (sc, what, descr)
struct awi_softc *sc;
***************
*** 1203,1226 ****
u_int32_t next, cur;
int i;
struct ifnet *ifp = sc->sc_ifp;
! u_int8_t *mptr;
! int mleft;
! struct mbuf *top = NULL, *m = NULL, *m1 = NULL;
cur = *descr;
-
if (cur & AWI_RXD_NEXT_LAST)
return;
!
! for (i=0;i<1000;i++) {
u_int16_t len;
u_int8_t state, rate, rssi, index;
u_int32_t frame;
u_int32_t rxts;
! top = 0;
!
next = awi_read_4(sc, cur + AWI_RXD_NEXT);
if (next & AWI_RXD_NEXT_LAST)
--- 1271,1293 ----
u_int32_t next, cur;
int i;
struct ifnet *ifp = sc->sc_ifp;
! int drain;
! struct mbuf *top = NULL, *m = NULL;
cur = *descr;
if (cur & AWI_RXD_NEXT_LAST)
return;
!
! for (i = 0; i < 1000; i++) {
u_int16_t len;
u_int8_t state, rate, rssi, index;
u_int32_t frame;
u_int32_t rxts;
! top = NULL;
! drain = 0;
!
next = awi_read_4(sc, cur + AWI_RXD_NEXT);
if (next & AWI_RXD_NEXT_LAST)
***************
*** 1233,1239 ****
index = awi_read_1 (sc, cur + AWI_RXD_INDEX);
frame = awi_read_4 (sc, cur + AWI_RXD_START_FRAME);
rxts = awi_read_4 (sc, cur + AWI_RXD_LOCALTIME);
!
/*
* only the low order bits of "frame" and "next" are valid.
* (the documentation doesn't mention this).
--- 1300,1306 ----
index = awi_read_1 (sc, cur + AWI_RXD_INDEX);
frame = awi_read_4 (sc, cur + AWI_RXD_START_FRAME);
rxts = awi_read_4 (sc, cur + AWI_RXD_LOCALTIME);
!
/*
* only the low order bits of "frame" and "next" are valid.
* (the documentation doesn't mention this).
***************
*** 1245,1296 ****
state |= AWI_RXD_ST_CONSUMED | AWI_RXD_ST_OWN;
awi_write_1(sc, cur + AWI_RXD_HOST_DESC_STATE, state);
} else {
! MGETHDR(top, M_DONTWAIT, MT_DATA);
! if (top != 0) {
! if (len >= MINCLSIZE)
! MCLGET(top, M_DONTWAIT);
!
! m = top;
! m->m_pkthdr.rcvif = ifp;
! m->m_pkthdr.len = 0;
! m->m_len = 0;
!
! mleft = (m->m_flags & M_EXT) ?
! MCLBYTES : MHLEN;
! mptr = mtod(m, u_int8_t *);
! }
! for(;;) {
! if (top != 0) {
! /* copy data into mbuf */
! while (len > 0) {
! int nmove = min (len, mleft);
!
! awi_read_bytes (sc, frame, mptr, nmove);
! len -= nmove;
! mleft -= nmove;
! mptr += nmove;
! frame += nmove;
!
! top->m_pkthdr.len += nmove;
! m->m_len += nmove;
!
! if (mleft == 0) {
! /* Get next mbuf.. */
! MGET(m1, M_DONTWAIT, MT_DATA);
! if (m1 == NULL) {
! m_freem(top);
! top = NULL;
! break;
! }
! m->m_next = m1;
! m = m1;
! m->m_len = 0;
!
! mleft = MLEN;
! mptr = mtod(m, u_int8_t *);
! }
}
}
state |= AWI_RXD_ST_CONSUMED | AWI_RXD_ST_OWN;
awi_write_1(sc, cur + AWI_RXD_HOST_DESC_STATE, state);
--- 1312,1335 ----
state |= AWI_RXD_ST_CONSUMED | AWI_RXD_ST_OWN;
awi_write_1(sc, cur + AWI_RXD_HOST_DESC_STATE, state);
} else {
! while (1) {
! m = awi_dump_rxchain1(sc, frame, len,
! (top == NULL) ? 1 : 0, drain);
! if (m != NULL) {
! if (top == NULL) {
! top = m;
! top->m_pkthdr.rcvif = ifp;
! top->m_pkthdr.len = len;
! } else {
! m_cat(top, m);
! top->m_pkthdr.len += len;
}
+ } else {
+ if (top)
+ m_freem(top);
+ drain++;
}
+
state |= AWI_RXD_ST_CONSUMED | AWI_RXD_ST_OWN;
awi_write_1(sc, cur + AWI_RXD_HOST_DESC_STATE, state);
***************
*** 1314,1319 ****
--- 1353,1360 ----
}
}
if (top) {
+ if ((sc->sc_ifp->if_flags & IFF_DEBUG) != 0)
+ printf("awi_rcv(len=%d)\n", top->m_pkthdr.len);
awi_rcv(sc, top, rxts, rssi);
top = 0;
}
------- =_aaaaaaaaaa0--