Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 22 Feb 2005 11:45:14 +0900
From:      Pyun YongHyeon <yongari@kt-is.co.kr>
To:        Andrew Belashov <bel@orel.ru>
Cc:        freebsd-sparc64@freebsd.org
Subject:   Re: Call for hme(4) testers
Message-ID:  <20050222024514.GA4799@kt-is.co.kr>
In-Reply-To: <4219CAA9.2010503@orel.ru>
References:  <20050221102511.GD1756@kt-is.co.kr> <4219CAA9.2010503@orel.ru>

next in thread | previous in thread | raw e-mail | index | archive | help

--SLDf9lqlvOQaIe6s
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Mon, Feb 21, 2005 at 02:48:57PM +0300, Andrew Belashov wrote:
 > >. make sure to invoke hme_init_locked() to unfreeze DMA enine when
 > 
 > What is "DMA enine"?
 > 

It's typo. It should be read "DMA engine".

 > 
 > I have patch collision with CURRENT:
 > 
Patch regenerated against latest CURRENT.
Sorry for inconvenience.

-- 
Regards,
Pyun YongHyeon
http://www.kr.freebsd.org/~yongari	|	yongari@freebsd.org

--SLDf9lqlvOQaIe6s
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="if_hme.diff.0222"

--- sys/dev/hme/if_hme.c.orig	Wed Feb  2 17:35:11 2005
+++ sys/dev/hme/if_hme.c	Tue Feb 22 11:36:53 2005
@@ -126,8 +126,6 @@
 static void	hme_rxcksum(struct mbuf *, u_int32_t);
 
 static void	hme_cdma_callback(void *, bus_dma_segment_t *, int, int);
-static void	hme_txdma_callback(void *, bus_dma_segment_t *, int,
-    bus_size_t, int);
 
 devclass_t hme_devclass;
 
@@ -223,14 +221,14 @@
 	if (error)
 		goto fail_ptag;
 
-	error = bus_dma_tag_create(sc->sc_pdmatag, max(0x10, sc->sc_burst), 0,
+	error = bus_dma_tag_create(sc->sc_pdmatag, imax(0x10, sc->sc_burst), 0,
 	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
 	    HME_NRXDESC, BUS_SPACE_MAXSIZE_32BIT, BUS_DMA_ALLOCNOW,
 	    NULL, NULL, &sc->sc_rdmatag);
 	if (error)
 		goto fail_ctag;
 
-	error = bus_dma_tag_create(sc->sc_pdmatag, max(0x10, sc->sc_burst), 0,
+	error = bus_dma_tag_create(sc->sc_pdmatag, imax(0x10, sc->sc_burst), 0,
 	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
 	    HME_NTXDESC, BUS_SPACE_MAXSIZE_32BIT, BUS_DMA_ALLOCNOW,
 	    NULL, NULL, &sc->sc_tdmatag);
@@ -439,8 +437,31 @@
 hme_tick(void *arg)
 {
 	struct hme_softc *sc = arg;
+	struct ifnet *ifp;
 	int s;
 
+
+	HME_LOCK(sc);
+	ifp = &sc->sc_arpcom.ac_if;
+
+	/*
+	 * Unload collision counters
+	 */
+	ifp->if_collisions +=
+		HME_MAC_READ_4(sc, HME_MACI_NCCNT) +
+		HME_MAC_READ_4(sc, HME_MACI_FCCNT) +
+		HME_MAC_READ_4(sc, HME_MACI_EXCNT) +
+		HME_MAC_READ_4(sc, HME_MACI_LTCNT);
+
+	/*
+	 * then clear the hardware counters.
+	 */
+	HME_MAC_WRITE_4(sc, HME_MACI_NCCNT, 0);
+	HME_MAC_WRITE_4(sc, HME_MACI_FCCNT, 0);
+	HME_MAC_WRITE_4(sc, HME_MACI_EXCNT, 0);
+	HME_MAC_WRITE_4(sc, HME_MACI_LTCNT, 0);
+	HME_UNLOCK(sc);
+
 	s = splnet();
 	mii_tick(sc->sc_mii);
 	splx(s);
@@ -463,11 +484,17 @@
 static void
 hme_stop(struct hme_softc *sc)
 {
+	struct ifnet *ifp;
 	u_int32_t v;
 	int n;
 
+	ifp = &sc->sc_arpcom.ac_if;
+	ifp->if_timer = 0;
 	callout_stop(&sc->sc_tick_ch);
 
+	/* mask all interrupts */
+	HME_SEB_WRITE_4(sc, HME_SEBI_IMASK, 0xffffffff);
+
 	/* Reset transmitter and receiver */
 	HME_SEB_WRITE_4(sc, HME_SEBI_RESET, HME_SEB_RESET_ETX |
 	    HME_SEB_RESET_ERX);
@@ -527,7 +554,7 @@
 	 * the mapping must be done in a way that a burst can start on a
 	 * natural boundary we might need to extend this.
 	 */
-	a = max(HME_MINRXALIGN, sc->sc_burst);
+	a = imax(HME_MINRXALIGN, sc->sc_burst);
 	/*
 	 * Make sure the buffer suitably aligned. The 2 byte offset is removed
 	 * when the mbuf is handed up. XXX: this ensures at least 16 byte
@@ -607,10 +634,10 @@
 	for (i = 0; i < HME_NTXQ; i++) {
 		td = &sc->sc_rb.rb_txdesc[i];
 		if (td->htx_m != NULL) {
-			m_freem(td->htx_m);
 			bus_dmamap_sync(sc->sc_tdmatag, td->htx_dmamap,
 			    BUS_DMASYNC_POSTWRITE);
 			bus_dmamap_unload(sc->sc_tdmatag, td->htx_dmamap);
+			m_freem(td->htx_m);
 			td->htx_m = NULL;
 		}
 		STAILQ_INSERT_TAIL(&sc->sc_rb.rb_txfreeq, td, htx_q);
@@ -879,69 +906,6 @@
 	hme_start_locked(ifp);
 }
 
-struct hme_txdma_arg {
-	struct hme_softc	*hta_sc;
-	struct hme_txdesc	*hta_htx;
-	int			hta_ndescs;
-};
-
-/*
- * XXX: this relies on the fact that segments returned by bus_dmamap_load_mbuf()
- * are readable from the nearest burst boundary on (i.e. potentially before
- * ds_addr) to the first boundary beyond the end. This is usually a safe
- * assumption to make, but is not documented.
- */
-static void
-hme_txdma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs,
-    bus_size_t totsz, int error)
-{
-	struct hme_txdma_arg *ta = xsc;
-	struct hme_txdesc *htx;
-	bus_size_t len = 0;
-	caddr_t txd;
-	u_int32_t flags = 0;
-	int i, tdhead, pci;
-
-	if (error != 0)
-		return;
-
-	tdhead = ta->hta_sc->sc_rb.rb_tdhead;
-	pci = ta->hta_sc->sc_pci;
-	txd = ta->hta_sc->sc_rb.rb_txd;
-	htx = ta->hta_htx;
-
-	if (ta->hta_sc->sc_rb.rb_td_nbusy + nsegs >= HME_NTXDESC) {
-		ta->hta_ndescs = -1;
-		return;
-	}
-	ta->hta_ndescs = nsegs;
-
-	for (i = 0; i < nsegs; i++) {
-		if (segs[i].ds_len == 0)
-			continue;
-
-		/* Fill the ring entry. */
-		flags = HME_XD_ENCODE_TSIZE(segs[i].ds_len);
-		if (len == 0)
-			flags |= HME_XD_SOP;
-		if (len + segs[i].ds_len == totsz)
-			flags |= HME_XD_EOP;
-		CTR5(KTR_HME, "hme_txdma_callback: seg %d/%d, ri %d, "
-		    "flags %#x, addr %#x", i + 1, nsegs, tdhead, (u_int)flags,
-		    (u_int)segs[i].ds_addr);
-		HME_XD_SETFLAGS(pci, txd, tdhead, flags);
-		HME_XD_SETADDR(pci, txd, tdhead, segs[i].ds_addr);
-
-		ta->hta_sc->sc_rb.rb_td_nbusy++;
-		htx->htx_lastdesc = tdhead;
-		tdhead = (tdhead + 1) % HME_NTXDESC;
-		len += segs[i].ds_len;
-	}
-	ta->hta_sc->sc_rb.rb_tdhead = tdhead;
-	KASSERT((flags & HME_XD_EOP) != 0,
-	    ("hme_txdma_callback: missed end of packet!"));
-}
-
 /* TX TCP/UDP checksum */
 static void
 hme_txcksum(struct mbuf *m, u_int32_t *cflags)
@@ -988,50 +952,65 @@
 static int
 hme_load_txmbuf(struct hme_softc *sc, struct mbuf *m0)
 {
-	struct hme_txdma_arg cba;
-	struct hme_txdesc *td;
-	int error, si, ri;
+	struct hme_txdesc *htx;
+	caddr_t txd;
+	int error;
+	int i, pci, si, ri, nseg;
 	u_int32_t flags, cflags = 0;
 
-	si = sc->sc_rb.rb_tdhead;
-	if ((td = STAILQ_FIRST(&sc->sc_rb.rb_txfreeq)) == NULL)
-		return (-1);
+	if ((htx = STAILQ_FIRST(&sc->sc_rb.rb_txfreeq)) == NULL) {
+		error = -1;
+		goto fail;
+	}
 	if ((m0->m_pkthdr.csum_flags & sc->sc_csum_features) != 0)
 		hme_txcksum(m0, &cflags);
-	cba.hta_sc = sc;
-	cba.hta_htx = td;
-	if ((error = bus_dmamap_load_mbuf(sc->sc_tdmatag, td->htx_dmamap,
-	     m0, hme_txdma_callback, &cba, 0)) != 0)
+	error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag, htx->htx_dmamap,
+	    m0, sc->sc_rb.rb_txsegs, &nseg, BUS_DMA_NOWAIT);
+	if (error != 0)
 		goto fail;
-	if (cba.hta_ndescs == -1) {
-		error = -1;
+	if (sc->sc_rb.rb_td_nbusy + nseg >= HME_NTXDESC) {
+		bus_dmamap_unload(sc->sc_tdmatag, htx->htx_dmamap);
+		error = -2;
 		goto fail;
 	}
-	bus_dmamap_sync(sc->sc_tdmatag, td->htx_dmamap,
-	    BUS_DMASYNC_PREWRITE);
+	bus_dmamap_sync(sc->sc_tdmatag, htx->htx_dmamap, BUS_DMASYNC_PREWRITE);
 
-	STAILQ_REMOVE_HEAD(&sc->sc_rb.rb_txfreeq, htx_q);
-	STAILQ_INSERT_TAIL(&sc->sc_rb.rb_txbusyq, td, htx_q);
-	td->htx_m = m0;
-
-	/* Turn descriptor ownership to the hme, back to forth. */
-	ri = sc->sc_rb.rb_tdhead;
-	CTR2(KTR_HME, "hme_load_mbuf: next desc is %d (%#x)",
-	    ri, HME_XD_GETFLAGS(sc->sc_pci, sc->sc_rb.rb_txd, ri));
-	do {
-		ri = (ri + HME_NTXDESC - 1) % HME_NTXDESC;
-		flags = HME_XD_GETFLAGS(sc->sc_pci, sc->sc_rb.rb_txd, ri) |
-		    HME_XD_OWN | cflags;
-		CTR3(KTR_HME, "hme_load_mbuf: activating ri %d, si %d (%#x)",
-		    ri, si, flags);
-		HME_XD_SETFLAGS(sc->sc_pci, sc->sc_rb.rb_txd, ri, flags);
-	} while (ri != si);
+	si = ri = sc->sc_rb.rb_tdhead;
+	txd = sc->sc_rb.rb_txd;
+	pci = sc->sc_pci;
+	for (i = 0; i < nseg; i++) {
+		/* Fill the ring entry. */
+		flags = HME_XD_ENCODE_TSIZE(sc->sc_rb.rb_txsegs[i].ds_len);
+		if (i == 0)
+			flags |= HME_XD_SOP | cflags;
+		else
+			flags |= HME_XD_OWN | cflags;
+		HME_XD_SETADDR(pci, txd, ri, sc->sc_rb.rb_txsegs[i].ds_addr);
+		HME_XD_SETFLAGS(pci, txd, ri, flags);
+		sc->sc_rb.rb_td_nbusy++;
+		htx->htx_lastdesc = ri;
+		ri = (ri + 1) % HME_NTXDESC;
+	}
+	sc->sc_rb.rb_tdhead = ri;
+
+	/* set EOP on the last descriptor */
+	ri = (ri + HME_NTXDESC - 1) % HME_NTXDESC;
+	flags = HME_XD_GETFLAGS(pci, txd, ri);
+	flags |= HME_XD_EOP;
+	HME_XD_SETFLAGS(pci, txd, ri, flags);
+
+	/* Turn the first descriptor ownership to the hme */
+	flags = HME_XD_GETFLAGS(sc->sc_pci, txd, si);
+	flags |= HME_XD_OWN;
+	HME_XD_SETFLAGS(pci, txd, si, flags);
 
+	STAILQ_REMOVE_HEAD(&sc->sc_rb.rb_txfreeq, htx_q);
+	STAILQ_INSERT_TAIL(&sc->sc_rb.rb_txbusyq, htx, htx_q);
+	htx->htx_m = m0;
 	/* start the transmission. */
 	HME_ETX_WRITE_4(sc, HME_ETXI_PENDING, HME_ETX_TP_DMAWAKEUP);
 	return (0);
 fail:
-	bus_dmamap_unload(sc->sc_tdmatag, td->htx_dmamap);
 	return (error);
 }
 
@@ -1103,30 +1082,23 @@
 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
 		return;
 
-	error = 0;
 	for (;;) {
 		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
 		if (m == NULL)
 			break;
 
 		error = hme_load_txmbuf(sc, m);
-		if (error == -1) {
+		if (error != 0) {
 			ifp->if_flags |= IFF_OACTIVE;
 			IFQ_DRV_PREPEND(&ifp->if_snd, m);
 			break;
-		} else if (error > 0) {
-			printf("hme_start: error %d while loading mbuf\n",
-			    error);
-		} else {
-			enq = 1;
-			BPF_MTAP(ifp, m);
 		}
+		enq++;
+		BPF_MTAP(ifp, m);
 	}
 
-	if (sc->sc_rb.rb_td_nbusy == HME_NTXDESC || error == -1)
-		ifp->if_flags |= IFF_OACTIVE;
 	/* Set watchdog timer if a packet was queued */
-	if (enq) {
+	if (enq > 0) {
 		bus_dmamap_sync(sc->sc_cdmatag, sc->sc_cdmamap,
 		    BUS_DMASYNC_PREWRITE);
 		ifp->if_timer = 5;
@@ -1143,23 +1115,6 @@
 	struct hme_txdesc *htx;
 	unsigned int ri, txflags;
 
-	/*
-	 * Unload collision counters
-	 */
-	ifp->if_collisions +=
-		HME_MAC_READ_4(sc, HME_MACI_NCCNT) +
-		HME_MAC_READ_4(sc, HME_MACI_FCCNT) +
-		HME_MAC_READ_4(sc, HME_MACI_EXCNT) +
-		HME_MAC_READ_4(sc, HME_MACI_LTCNT);
-
-	/*
-	 * then clear the hardware counters.
-	 */
-	HME_MAC_WRITE_4(sc, HME_MACI_NCCNT, 0);
-	HME_MAC_WRITE_4(sc, HME_MACI_FCCNT, 0);
-	HME_MAC_WRITE_4(sc, HME_MACI_EXCNT, 0);
-	HME_MAC_WRITE_4(sc, HME_MACI_LTCNT, 0);
-
 	htx = STAILQ_FIRST(&sc->sc_rb.rb_txbusyq);
 	bus_dmamap_sync(sc->sc_cdmatag, sc->sc_cdmamap, BUS_DMASYNC_POSTREAD);
 	/* Fetch current position in the transmit ring */
@@ -1197,17 +1152,13 @@
 		STAILQ_INSERT_TAIL(&sc->sc_rb.rb_txfreeq, htx, htx_q);
 		htx = STAILQ_FIRST(&sc->sc_rb.rb_txbusyq);
 	}
-	/* Turn off watchdog */
-	if (sc->sc_rb.rb_td_nbusy == 0)
-		ifp->if_timer = 0;
+	/* Turn off watchdog if hme(4) transmitted queued packet */
+	ifp->if_timer = sc->sc_rb.rb_td_nbusy > 0 ? 5 : 0;
 
 	/* Update ring */
 	sc->sc_rb.rb_tdtail = ri;
 
 	hme_start_locked(ifp);
-
-	if (sc->sc_rb.rb_td_nbusy == 0)
-		ifp->if_timer = 0;
 }
 
 /*
@@ -1325,6 +1276,12 @@
 	}
 
 	HME_WHINE(sc->sc_dev, "error signaled, status=%#x\n", status);
+	/* check for fatal errors that needs reset to unfreeze DMA engine */
+	if ((status & (HME_SEB_STAT_SLVERR | HME_SEB_STAT_SLVERR |
+	    HME_SEB_STAT_TXTERR | HME_SEB_STAT_TXPERR | HME_SEB_STAT_TXLERR |
+	    HME_SEB_STAT_TXEACK | HME_SEB_STAT_RXTERR | HME_SEB_STAT_RXPERR |
+	    HME_SEB_STAT_RXLATERR | HME_SEB_STAT_RXERR)) != 0)
+		hme_init_locked(sc);
 }
 
 void
@@ -1347,7 +1304,6 @@
 		hme_rint(sc);
 	HME_UNLOCK(sc);
 }
-
 
 static void
 hme_watchdog(struct ifnet *ifp)
--- sys/dev/hme/if_hmevar.h.orig	Mon Nov 22 15:46:30 2004
+++ sys/dev/hme/if_hmevar.h	Tue Feb 22 11:33:22 2005
@@ -100,6 +100,7 @@
 	/* Descriptors */
 	struct hme_rxdesc	rb_rxdesc[HME_NRXDESC];
 	struct hme_txdesc	rb_txdesc[HME_NTXQ];
+	bus_dma_segment_t	rb_txsegs[HME_NTXDESC];
 
 	struct	hme_txdq	rb_txfreeq;
 	struct	hme_txdq	rb_txbusyq;

--SLDf9lqlvOQaIe6s--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050222024514.GA4799>