PERFORCE change 66439 for review

Sam Leffler sam at FreeBSD.org
Sat Dec 4 23:06:21 PST 2004


http://perforce.freebsd.org/chv.cgi?CH=66439

Change 66439 by sam at sam_ebb on 2004/12/05 07:05:37

	Revamp descriptor allocation to improve success on systems
	with fragment memory and for forthcoming multi-*ssid support.
	
	o encapsulate descriptor+buffer state in new ath_dmadesc struct
	o manage tx+rx+beacon dma state independently
	o remove some assumptions about there being only one beacon frame
	o improve error handling on failures during tx/rx setup

Affected files ...

.. //depot/projects/wifi/sys/dev/ath/if_ath.c#38 edit
.. //depot/projects/wifi/sys/dev/ath/if_athvar.h#15 edit

Differences ...

==== //depot/projects/wifi/sys/dev/ath/if_ath.c#38 (text+ko) ====

@@ -122,6 +122,8 @@
 static void	ath_bstuck_proc(void *, int);
 static void	ath_beacon_free(struct ath_softc *);
 static void	ath_beacon_config(struct ath_softc *);
+static void	ath_descdma_cleanup(struct ath_softc *sc,
+			struct ath_descdma *, ath_bufhead *);
 static int	ath_desc_alloc(struct ath_softc *);
 static void	ath_desc_free(struct ath_softc *);
 static struct ieee80211_node *ath_node_alloc(struct ieee80211_node_table *);
@@ -236,6 +238,8 @@
 #define	KEYPRINTF(sc, k, ix, mac)
 #endif
 
+MALLOC_DEFINE(M_ATHDEV, "athdev", "ath driver dma buffers");
+
 int
 ath_attach(u_int16_t devid, struct ath_softc *sc)
 {
@@ -1679,12 +1683,17 @@
 static int
 ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni)
 {
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ieee80211com *ic = ni->ni_ic;
 	struct ath_buf *bf;
 	struct mbuf *m;
 	int error;
 
-	bf = sc->sc_bcbuf;
+	bf = STAILQ_FIRST(&sc->sc_bbuf);
+	if (bf == NULL) {
+		DPRINTF(sc, ATH_DEBUG_BEACON, "%s: no dma buffers\n", __func__);
+		sc->sc_stats.ast_be_nombuf++;	/* XXX */
+		return ENOMEM;			/* XXX */
+	}
 	if (bf->bf_m != NULL) {
 		bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
 		m_freem(bf->bf_m);
@@ -1724,8 +1733,8 @@
 #define	USE_SHPREAMBLE(_ic) \
 	(((_ic)->ic_flags & (IEEE80211_F_SHPREAMBLE | IEEE80211_F_USEBARKER))\
 		== IEEE80211_F_SHPREAMBLE)
-	struct ieee80211com *ic = &sc->sc_ic;
 	struct ieee80211_node *ni = bf->bf_node;
+	struct ieee80211com *ic = ni->ni_ic;
 	struct mbuf *m = bf->bf_m;
 	struct ath_hal *ah = sc->sc_ah;
 	struct ath_node *an = ATH_NODE(ni);
@@ -1798,8 +1807,9 @@
 ath_beacon_proc(void *arg, int pending)
 {
 	struct ath_softc *sc = arg;
-	struct ieee80211com *ic = &sc->sc_ic;
-	struct ath_buf *bf = sc->sc_bcbuf;
+	struct ath_buf *bf = STAILQ_FIRST(&sc->sc_bbuf);
+	struct ieee80211_node *ni = bf->bf_node;
+	struct ieee80211com *ic = ni->ni_ic;
 	struct ath_hal *ah = sc->sc_ah;
 	struct mbuf *m;
 	int ncabq, error, otherant;
@@ -1935,14 +1945,15 @@
 static void
 ath_beacon_free(struct ath_softc *sc)
 {
-	struct ath_buf *bf = sc->sc_bcbuf;
+	struct ath_buf *bf;
 
-	if (bf->bf_m != NULL) {
-		bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
-		m_freem(bf->bf_m);
-		bf->bf_m = NULL;
-		bf->bf_node = NULL;
-	}
+	STAILQ_FOREACH(bf, &sc->sc_bbuf, bf_list)
+		if (bf->bf_m != NULL) {
+			bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
+			m_freem(bf->bf_m);
+			bf->bf_m = NULL;
+			bf->bf_node = NULL;
+		}
 }
 
 /*
@@ -2088,121 +2099,162 @@
 }
 
 static int
-ath_desc_alloc(struct ath_softc *sc)
+ath_descdma_setup(struct ath_softc *sc,
+	struct ath_descdma *dd, ath_bufhead *head,
+	const char *name, int nbuf, int ndesc)
 {
-#define	DS2PHYS(_sc, _ds) \
-	((_sc)->sc_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_sc)->sc_desc))
-	int i, bsize, error;
+#define	DS2PHYS(_dd, _ds) \
+	((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
+	struct ifnet *ifp = &sc->sc_if;
 	struct ath_desc *ds;
 	struct ath_buf *bf;
+	int i, bsize, error;
 
+	DPRINTF(sc, ATH_DEBUG_RESET, "%s: %s DMA: %u buffers %u desc/buf\n",
+	    __func__, name, nbuf, ndesc);
+
+	dd->dd_name = name;
+
 	/* allocate descriptors */
-	sc->sc_desc_len = sizeof(struct ath_desc) *
-				(ATH_TXBUF * ATH_TXDESC + ATH_RXBUF + 1);
-	error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, &sc->sc_ddmamap);
-	if (error != 0)
+	dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc;
+	error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, &dd->dd_dmamap);
+	if (error != 0) {
+		if_printf(ifp, "unable to create dmamap for %s descriptors, "
+			"error %u\n", dd->dd_name, error);
 		return error;
+	}
 
-	error = bus_dmamem_alloc(sc->sc_dmat, (void**) &sc->sc_desc,
-				 BUS_DMA_NOWAIT, &sc->sc_ddmamap);
-	if (error != 0)
+	error = bus_dmamem_alloc(sc->sc_dmat, (void**) &dd->dd_desc,
+				 BUS_DMA_NOWAIT, &dd->dd_dmamap);
+	if (error != 0) {
+		if_printf(ifp, "unable to alloc memory for %u %s descriptors, "
+			"error %u\n", nbuf * ndesc, dd->dd_name, error);
 		goto fail0;
+	}
 
-	error = bus_dmamap_load(sc->sc_dmat, sc->sc_ddmamap,
-				sc->sc_desc, sc->sc_desc_len,
-				ath_load_cb, &sc->sc_desc_paddr,
+	error = bus_dmamap_load(sc->sc_dmat, dd->dd_dmamap,
+				dd->dd_desc, dd->dd_desc_len,
+				ath_load_cb, &dd->dd_desc_paddr,
 				BUS_DMA_NOWAIT);
-	if (error != 0)
+	if (error != 0) {
+		if_printf(ifp, "unable to map %s descriptors, error %u\n",
+			dd->dd_name, error);
 		goto fail1;
+	}
 
-	ds = sc->sc_desc;
-	DPRINTF(sc, ATH_DEBUG_ANY, "%s: DMA map: %p (%lu) -> %p (%lu)\n",
-	    __func__, ds, (u_long) sc->sc_desc_len, (caddr_t) sc->sc_desc_paddr,
-	    /*XXX*/ (u_long) sc->sc_desc_len);
+	ds = dd->dd_desc;
+	DPRINTF(sc, ATH_DEBUG_RESET, "%s: %s DMA map: %p (%lu) -> %p (%lu)\n",
+	    __func__, dd->dd_name, ds, (u_long) dd->dd_desc_len,
+	    (caddr_t) dd->dd_desc_paddr, /*XXX*/ (u_long) dd->dd_desc_len);
 
-	/* allocate buffers */
-	bsize = sizeof(struct ath_buf) * (ATH_TXBUF + ATH_RXBUF + 1);
-	bf = malloc(bsize, M_DEVBUF, M_NOWAIT | M_ZERO);
-	if (bf == NULL)
+	/* allocate rx buffers */
+	bsize = sizeof(struct ath_buf) * nbuf;
+	bf = malloc(bsize, M_ATHDEV, M_NOWAIT | M_ZERO);
+	if (bf == NULL) {
+		if_printf(ifp, "malloc of %s buffers failed, size %u\n",
+			dd->dd_name, bsize);
 		goto fail2;
-	sc->sc_bufptr = bf;
-
-	STAILQ_INIT(&sc->sc_rxbuf);
-	for (i = 0; i < ATH_RXBUF; i++, bf++, ds++) {
-		bf->bf_desc = ds;
-		bf->bf_daddr = DS2PHYS(sc, ds);
-		error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT,
-					  &bf->bf_dmamap);
-		if (error != 0)
-			break;
-		STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
 	}
+	dd->dd_bufptr = bf;
 
-	STAILQ_INIT(&sc->sc_txbuf);
-	for (i = 0; i < ATH_TXBUF; i++, bf++, ds += ATH_TXDESC) {
+	STAILQ_INIT(head);
+	for (i = 0; i < nbuf; i++, bf++, ds += ndesc) {
 		bf->bf_desc = ds;
-		bf->bf_daddr = DS2PHYS(sc, ds);
+		bf->bf_daddr = DS2PHYS(dd, ds);
 		error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT,
-					  &bf->bf_dmamap);
-		if (error != 0)
-			break;
-		STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
+				&bf->bf_dmamap);
+		if (error != 0) {
+			if_printf(ifp, "unable to create dmamap for %s "
+				"buffer %u, error %u\n", dd->dd_name, i, error);
+			ath_descdma_cleanup(sc, dd, head);
+			return error;
+		}
+		STAILQ_INSERT_TAIL(head, bf, bf_list);
 	}
-
-	/* beacon buffer */
-	bf->bf_desc = ds;
-	bf->bf_daddr = DS2PHYS(sc, ds);
-	error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, &bf->bf_dmamap);
-	if (error != 0)
-		return error;
-	sc->sc_bcbuf = bf;
 	return 0;
-
 fail2:
-	bus_dmamap_unload(sc->sc_dmat, sc->sc_ddmamap);
+	bus_dmamap_unload(sc->sc_dmat, dd->dd_dmamap);
 fail1:
-	bus_dmamem_free(sc->sc_dmat, sc->sc_desc, sc->sc_ddmamap);
+	bus_dmamem_free(sc->sc_dmat, dd->dd_desc, dd->dd_dmamap);
 fail0:
-	bus_dmamap_destroy(sc->sc_dmat, sc->sc_ddmamap);
-	sc->sc_ddmamap = NULL;
+	bus_dmamap_destroy(sc->sc_dmat, dd->dd_dmamap);
+	memset(dd, 0, sizeof(*dd));
 	return error;
 #undef DS2PHYS
 }
 
 static void
-ath_desc_free(struct ath_softc *sc)
+ath_descdma_cleanup(struct ath_softc *sc,
+	struct ath_descdma *dd, ath_bufhead *head)
 {
 	struct ath_buf *bf;
+	struct ieee80211_node *ni;
 
-	bus_dmamap_unload(sc->sc_dmat, sc->sc_ddmamap);
-	bus_dmamem_free(sc->sc_dmat, sc->sc_desc, sc->sc_ddmamap);
-	bus_dmamap_destroy(sc->sc_dmat, sc->sc_ddmamap);
+	bus_dmamap_unload(sc->sc_dmat, dd->dd_dmamap);
+	bus_dmamem_free(sc->sc_dmat, dd->dd_desc, dd->dd_dmamap);
+	bus_dmamap_destroy(sc->sc_dmat, dd->dd_dmamap);
 
-	/*
-	 * NB: TX queues have already been freed in ath_draintxq(),
-	 * which must be called before calling this function.
-	 */
-
-	STAILQ_FOREACH(bf, &sc->sc_txbuf, bf_list)
-		bus_dmamap_destroy(sc->sc_dmat, bf->bf_dmamap);
-	STAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
+	STAILQ_FOREACH(bf, head, bf_list) {
 		if (bf->bf_m) {
-			bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
-			bus_dmamap_destroy(sc->sc_dmat, bf->bf_dmamap);
 			m_freem(bf->bf_m);
 			bf->bf_m = NULL;
 		}
+		if (bf->bf_dmamap != NULL) {
+			bus_dmamap_destroy(sc->sc_dmat, bf->bf_dmamap);
+			bf->bf_dmamap = NULL;
+		}
+		ni = bf->bf_node;
+		bf->bf_node = NULL;
+		if (ni != NULL) {
+			/*
+			 * Reclaim node reference.
+			 */
+			ieee80211_free_node(ni);
+		}
 	}
-	if (sc->sc_bcbuf != NULL) {
-		bus_dmamap_unload(sc->sc_dmat, sc->sc_bcbuf->bf_dmamap);
-		bus_dmamap_destroy(sc->sc_dmat, sc->sc_bcbuf->bf_dmamap);
-		sc->sc_bcbuf = NULL;
+
+	STAILQ_INIT(head);
+	free(dd->dd_bufptr, M_ATHDEV);
+	memset(dd, 0, sizeof(*dd));
+}
+
+static int
+ath_desc_alloc(struct ath_softc *sc)
+{
+	int error;
+
+	error = ath_descdma_setup(sc, &sc->sc_rxdma, &sc->sc_rxbuf,
+			"rx", ATH_RXBUF, 1);
+	if (error != 0)
+		return error;
+
+	error = ath_descdma_setup(sc, &sc->sc_txdma, &sc->sc_txbuf,
+			"tx", ATH_TXBUF, ATH_TXDESC);
+	if (error != 0) {
+		ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf);
+		return error;
+	}
+
+	error = ath_descdma_setup(sc, &sc->sc_bdma, &sc->sc_bbuf,
+			"beacon", 1, 1);
+	if (error != 0) {
+		ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf);
+		ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf);
+		return error;
 	}
+	return 0;
+}
 
-	STAILQ_INIT(&sc->sc_rxbuf);
-	STAILQ_INIT(&sc->sc_txbuf);
-	free(sc->sc_bufptr, M_DEVBUF);
-	sc->sc_bufptr = NULL;
+static void
+ath_desc_free(struct ath_softc *sc)
+{
+
+	if (sc->sc_bdma.dd_desc_len != 0)
+		ath_descdma_cleanup(sc, &sc->sc_bdma, &sc->sc_bbuf);
+	if (sc->sc_txdma.dd_desc_len != 0)
+		ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf);
+	if (sc->sc_rxdma.dd_desc_len != 0)
+		ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf);
 }
 
 static struct ieee80211_node *
@@ -2296,11 +2348,9 @@
 	struct ath_hal *ah = sc->sc_ah;
 	int error;
 	struct mbuf *m;
-struct mbuf *morig; /*XXX*/
 	struct ath_desc *ds;
 
 	m = bf->bf_m;
-morig = m;	/* XXX */
 	if (m == NULL) {
 		/*
 		 * NB: by assigning a page to the rx dma buffer we
@@ -2320,7 +2370,8 @@
 		bf->bf_m = m;
 		m->m_pkthdr.len = m->m_len = m->m_ext.ext_size;
 
-		error = bus_dmamap_load_mbuf(sc->sc_dmat, bf->bf_dmamap, m,
+		error = bus_dmamap_load_mbuf(sc->sc_dmat,
+					     bf->bf_dmamap, m,
 					     ath_mbuf_load_cb, bf,
 					     BUS_DMA_NOWAIT);
 		if (error != 0) {
@@ -2333,7 +2384,6 @@
 		KASSERT(bf->bf_nseg == 1, ("%s: multi-segment packet; nseg %u",
 			__func__, bf->bf_nseg));
 	}
-	KASSERT(m->m_next == NULL, ("m_next %p morig %p (2)", m->m_next, morig));
 	bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREREAD);
 
 	/*
@@ -2428,8 +2478,8 @@
 ath_rx_proc(void *arg, int npending)
 {
 #define	PA2DESC(_sc, _pa) \
-	((struct ath_desc *)((caddr_t)(_sc)->sc_desc + \
-		((_pa) - (_sc)->sc_desc_paddr)))
+	((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \
+		((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
 	struct ath_softc *sc = arg;
 	struct ath_buf *bf;
 	struct ieee80211com *ic = &sc->sc_ic;
@@ -2482,10 +2532,6 @@
 #endif
 		if (status == HAL_EINPROGRESS)
 			break;
-		if (m->m_next != NULL) {	/* XXX */
-			if_printf(ifp, "m_next %p, patching!\n", m->m_next);
-			m->m_next = NULL;
-		}
 		STAILQ_REMOVE_HEAD(&sc->sc_rxbuf, bf_list);
 		if (ds->ds_rxstat.rs_more) {
 			/*
@@ -2535,7 +2581,7 @@
 				len = ds->ds_rxstat.rs_datalen;
 				if (len >= sizeof (struct ieee80211_frame)) {
 					bus_dmamap_sync(sc->sc_dmat,
-					    bf->bf_dmamap, 
+					    bf->bf_dmamap,
 					    BUS_DMASYNC_POSTREAD);
 					ieee80211_notify_michael_failure(ic,
 					    mtod(m, struct ieee80211_frame *),
@@ -2562,7 +2608,7 @@
 		 * when the rx descriptor is setup again to receive
 		 * another frame.
 		 */
-		bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, 
+		bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
 		    BUS_DMASYNC_POSTREAD);
 		bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
 		bf->bf_m = NULL;
@@ -2956,7 +3002,6 @@
 	bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE);
 	bf->bf_m = m0;
 	bf->bf_node = ni;			/* NB: held reference */
-{ struct mbuf *n; bf->bf_nm = 0; for (n = bf->bf_m; n != NULL; n = n->m_next) bf->bf_mshadow[bf->bf_nm++] = n; }/*XXX*/
 
 	/* setup descriptors */
 	ds = bf->bf_desc;
@@ -3548,8 +3593,8 @@
 ath_stoprecv(struct ath_softc *sc)
 {
 #define	PA2DESC(_sc, _pa) \
-	((struct ath_desc *)((caddr_t)(_sc)->sc_desc + \
-		((_pa) - (_sc)->sc_desc_paddr)))
+	((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \
+		((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
 	struct ath_hal *ah = sc->sc_ah;
 
 	ath_hal_stoppcurecv(ah);	/* disable PCU */

==== //depot/projects/wifi/sys/dev/ath/if_athvar.h#15 (text+ko) ====

@@ -83,16 +83,28 @@
 struct ath_buf {
 	STAILQ_ENTRY(ath_buf)	bf_list;
 	int			bf_nseg;
-	bus_dmamap_t		bf_dmamap;	/* DMA map of the buffer */
 	struct ath_desc		*bf_desc;	/* virtual addr of desc */
 	bus_addr_t		bf_daddr;	/* physical addr of desc */
+	bus_dmamap_t		bf_dmamap;	/* DMA map for mbuf chain */
 	struct mbuf		*bf_m;		/* mbuf for buf */
 	struct ieee80211_node	*bf_node;	/* pointer to the node */
 	bus_size_t		bf_mapsize;
 #define	ATH_MAX_SCATTER		64
 	bus_dma_segment_t	bf_segs[ATH_MAX_SCATTER];
-struct mbuf *bf_mshadow[ATH_MAX_SCATTER];/*XXX*/
-int bf_nm;
+};
+typedef STAILQ_HEAD(, ath_buf) ath_bufhead;
+
+/*
+ * DMA state for tx/rx descriptors.
+ */
+struct ath_descdma {
+	const char*		dd_name;
+	struct ath_desc		*dd_desc;	/* descriptors */
+	bus_addr_t		dd_desc_paddr;	/* physical addr of dd_desc */
+	bus_addr_t		dd_desc_len;	/* size of dd_desc */
+	bus_dma_segment_t	dd_dseg;
+	bus_dmamap_t		dd_dmamap;	/* DMA map for descriptors */
+	struct ath_buf		*dd_bufptr;	/* associated buffers */
 };
 
 /*
@@ -191,36 +203,32 @@
 	} u_rx_rt;
 	int			sc_rx_th_len;
 
-	struct ath_desc		*sc_desc;	/* TX/RX descriptors */
-	bus_dma_segment_t	sc_dseg;
-	bus_dmamap_t		sc_ddmamap;	/* DMA map for descriptors */
-	bus_addr_t		sc_desc_paddr;	/* physical addr of sc_desc */
-	bus_addr_t		sc_desc_len;	/* size of sc_desc */
-
 	struct task		sc_fataltask;	/* fatal int processing */
 
-	STAILQ_HEAD(, ath_buf)	sc_rxbuf;	/* receive buffer */
+	struct ath_descdma	sc_rxdma;	/* RX descriptos */
+	ath_bufhead		sc_rxbuf;	/* receive buffer */
 	u_int32_t		*sc_rxlink;	/* link ptr in last RX desc */
 	struct task		sc_rxtask;	/* rx int processing */
 	struct task		sc_rxorntask;	/* rxorn int processing */
 	u_int8_t		sc_defant;	/* current default antenna */
 	u_int8_t		sc_rxotherant;	/* rx's on non-default antenna*/
 
+	struct ath_descdma	sc_txdma;	/* TX descriptors */
+	ath_bufhead		sc_txbuf;	/* transmit buffer */
+	struct mtx		sc_txbuflock;	/* txbuf lock */
 	int			sc_tx_timer;	/* transmit timeout */
-	STAILQ_HEAD(, ath_buf)	sc_txbuf;	/* transmit buffer */
-	struct mtx		sc_txbuflock;	/* txbuf lock */
 	u_int			sc_txqsetup;	/* h/w queues setup */
 	u_int			sc_txintrperiod;/* tx interrupt batching */
 	struct ath_txq		sc_txq[HAL_NUM_TX_QUEUES];
 	struct ath_txq		*sc_ac2q[5];	/* WME AC -> h/w q map */ 
 	struct task		sc_txtask;	/* tx int processing */
 
+	struct ath_descdma	sc_bdma;	/* beacon descriptors */
+	ath_bufhead		sc_bbuf;	/* beacon buffers */
 	u_int			sc_bhalq;	/* HAL q for outgoing beacons */
 	u_int			sc_bmisscount;	/* missed beacon transmits */
 	u_int32_t		sc_ant_tx[8];	/* recent tx frames/antenna */
 	struct ath_txq		*sc_cabq;	/* tx q for cab frames */
-	struct ath_buf		*sc_bcbuf;	/* beacon buffer */
-	struct ath_buf		*sc_bufptr;	/* allocated buffer ptr */
 	struct ieee80211_beacon_offsets sc_boff;/* dynamic update state */
 	struct task		sc_bmisstask;	/* bmiss int processing */
 	struct task		sc_bstucktask;	/* stuck beacon processing */


More information about the p4-projects mailing list