Subject: awi patch against 1.7
To: None <tech-net@netbsd.org>
From: Jun-ichiro itojun Hagino <itojun@iijlab.net>
List: tech-net
Date: 11/08/1999 17:00:53
	(sorry if two many awi-related messages are bothering you)

	the patch is against 1.7.  this includes micheal's fixes and
	fix to mbuf duplicated free issue.  works quite fine for me
	except roaming issues.

itojun

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 21:52:06
***************
*** 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 *));
***************
*** 812,817 ****
--- 813,819 ----
  	struct mbuf *m;
  {
  	printf("%s: ctl\n", sc->sc_dev.dv_xname);
+ 	m_freem(m);
  }
  
  void
***************
*** 887,892 ****
--- 889,897 ----
  	m_freem(m);
  }
  
+ static int rcvstat[16];
+ static int totrcvstat;
+ 
  void
  awi_rcv_mgt (sc, m, rxts, rssi) 
  	struct awi_softc *sc;
***************
*** 937,944 ****
--- 942,967 ----
  		
  	mgthdr = framehdr + 24;	/* XXX magic */
  	
+ 	rcvstat[subtype]++;
+ 	totrcvstat++;
+ 	if ((ifp->if_flags & IFF_DEBUG) && totrcvstat % 50 == 0) {
+ 		int i;
+ 		printf("rcvstat:");
+ 		for (i = 0; i < 16; i++)
+ 			printf(" %d", rcvstat[i]);
+ 		printf("\n");
+ 	}
+ 
  	switch (subtype) {
  
+ 	case IEEEWL_SUBTYPE_ASSOCREQ:
+ 		/*
+ 		 * this indicates that we've being asked to join an AP
+ 		 */
+ 		printf("%s: assoc_req\n", sc->sc_dev.dv_xname);
+ 
+ 		break;
+ 		
  	case IEEEWL_SUBTYPE_ASSOCRESP:
  		/*
  		 * this acknowledges that the AP will be forwarding traffic
***************
*** 970,981 ****
  		/* XXX set media status to "i see carrier" */
  		break;
  		
  	case IEEEWL_SUBTYPE_REASSOCRESP:
  		/*
  		 * this indicates that we've moved from one AP to another
  		 * within the same DS.
  		 */
! 		printf("reassoc_resp\n");
  
  		break;
  		
--- 993,1013 ----
  		/* XXX set media status to "i see carrier" */
  		break;
  		
+ 	case IEEEWL_SUBTYPE_REASSOCREQ:
+ 		/*
+ 		 * this indicates that we've being asked to move from one AP
+ 		 * to another within the same DS? 
+ 		 */
+ 		printf("%s: reassoc_req\n", sc->sc_dev.dv_xname);
+ 
+ 		break;
+ 		
  	case IEEEWL_SUBTYPE_REASSOCRESP:
  		/*
  		 * this indicates that we've moved from one AP to another
  		 * within the same DS.
  		 */
! 		printf("%s: reassoc_resp\n", sc->sc_dev.dv_xname);
  
  		break;
  		
***************
*** 1071,1077 ****
  		break;
  		
  	case IEEEWL_SUBTYPE_DISSOC:
! 		printf("dissoc\n");
  
  		break;
  		
--- 1103,1109 ----
  		break;
  		
  	case IEEEWL_SUBTYPE_DISSOC:
! 		printf("%s: dissoc\n", sc->sc_dev.dv_xname);
  
  		break;
  		
***************
*** 1105,1112 ****
  		sc->sc_new_bss = 1;
  		awi_send_authreq(sc);
  		break;
  	default:
! 		printf("unk mgt subtype %x\n", subtype);
  		break;
  	}
  	m_freem(m);		/* done.. */
--- 1137,1146 ----
  		sc->sc_new_bss = 1;
  		awi_send_authreq(sc);
  		break;
+ 
  	default:
! 		printf("%s: unk mgt subtype %x\n",
! 		       sc->sc_dev.dv_xname, subtype);
  		break;
  	}
  	m_freem(m);		/* done.. */
***************
*** 1185,1199 ****
  
  	case IEEEWL_FC_TYPE_CTL << IEEEWL_FC_TYPE_SHIFT:
  		awi_rcv_ctl (sc, m);
  	default:
  		goto drop;
  	}
  
   drop:
! 	if (m) m_freem(m);
  }
  
  
  void
  awi_dump_rxchain (sc, what, descr)
  	struct awi_softc *sc;
--- 1219,1312 ----
  
  	case IEEEWL_FC_TYPE_CTL << IEEEWL_FC_TYPE_SHIFT:
  		awi_rcv_ctl (sc, m);
+ 		m = 0;
+ 		break;
+ 
  	default:
  		goto drop;
  	}
  
   drop:
! 	if (m)
! 		m_freem(m);
  }
  
  
+ 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;
+ 	struct mbuf *top = NULL;
+ 	struct mbuf *mlast = NULL;
+ 	int nmove;
+ 	int mlen;
+ 
+ 	if (drain)
+ 		goto drain;
+ 
+ #if 0
+ 	if ((sc->sc_ifp->if_flags & IFF_DEBUG) != 0)
+ 		printf("awi_dump_rxchain1(%d)\n", len);
+ #endif
+ 	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 && len > MINCLSIZE) {
+ 			MCLGET(m, M_DONTWAIT);
+ 			if ((m->m_flags & M_EXT) == 0) {
+ 				m_free(m);
+ 				m = NULL;
+ 			}
+ 			mlen = MCLBYTES;
+ 		}
+ 		if (m == NULL) {
+ 			m_freem(top);
+ 			top = NULL;
+ 			goto drain;
+ 		}
+ 		if (top == NULL)
+ 			top = m;
+ 
+ 		nmove = min(len, mlen);
+ #if 0
+ 		if ((sc->sc_ifp->if_flags & IFF_DEBUG) != 0)
+ 			printf("nmove=%d\n", nmove);
+ #endif
+ 		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:
+ #if 0
+ 	while (len > 0) {
+ 		nmove = min(len, sizeof(junk));
+ 		awi_read_bytes(sc, frame, junk, nmove);
+ 		len -= nmove;
+ 	}
+ #endif
+ 	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)
--- 1316,1338 ----
  	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).
--- 1345,1351 ----
  		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);
  
--- 1357,1381 ----
  			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;
  					}
+ 					m = NULL;
+ 				} else {
+ 					m_freem(top);
+ 					top = NULL;
+ 					drain++;
  				}
+ 
  				state |= AWI_RXD_ST_CONSUMED | AWI_RXD_ST_OWN;
  				awi_write_1(sc, cur + AWI_RXD_HOST_DESC_STATE, state);
  
***************
*** 1314,1319 ****
--- 1399,1408 ----
  			}
  		}
  		if (top) {
+ #if 0
+ 			if ((sc->sc_ifp->if_flags & IFF_DEBUG) != 0)
+ 				printf("awi_rcv(len=%d)\n", top->m_pkthdr.len);
+ #endif
  			awi_rcv(sc, top, rxts, rssi);
  			top = 0;
  		}