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--