Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Sep 2002 15:48:47 +0200 (CEST)
From:      Harti Brandt <brandt@fokus.gmd.de>
To:        Bruce Evans <bde@zeta.org.au>
Cc:        Don Lewis <dl-freebsd@catspoiler.org>, <brandt@fokus.gmd.de>, <phk@critter.freebsd.dk>, <archie@dellroad.org>, <joe@FreeBSD.org>, <obrien@FreeBSD.org>, <cvs-committers@FreeBSD.org>, <cvs-all@FreeBSD.org>
Subject:   Re: cvs commit: src/sys/kern kern_timeout.c 
Message-ID:  <20020917153943.X812-200000@beagle.fokus.gmd.de>
In-Reply-To: <20020917233828.H11067-100000@gamplex.bde.org>

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

[-- Attachment #1 --]
On Tue, 17 Sep 2002, Bruce Evans wrote:

BE>On Tue, 17 Sep 2002, Don Lewis wrote:
BE>
BE>> On 17 Sep, Harti Brandt wrote:
BE>> ....
BE>> > (1) replaced all calls to DELAY(1) with a bus_space_read_4() on a card
BE>> > address. Because there are 184 DELAY(1) calls in each xl_mii_readreg each
BE>> > of which takes a mean of 8.5usecs this cuts down the overall time from
BE>> > 1.8msec to around 320usecs.
BE>>
BE>> I think we're probably ok here.  The standard says the minimum high and
BE>> low times for the clock signal are 160ns, with a minimum clock period of
BE>> 400ns.  If I do the math correctly, your scheme wiggles something about
BE>> every 1.7us.
BE>
BE>Maybe the total time can be reduced a lot more by using the minimum delays
BE>specified by the standard (using nanodelay(9unimplemented)).  You would
BE>find out if there is hardware that doesn't comply with the standard :-).

I have reduced the time to around 240usec per readreg and 950usec per
xl_status_update by removing the delays altogether. This is possible,
because the macros used to toggle the bits first do a read to the address
and then only a write. The delay introduced by this read is enough it
seems. The time could be reduced further (if we had nanodelay()) by not
reading the registers, but by using nanodelay() and writes. This is
possible because we always know what we have in the register so there is
no point in reading it.

I can reduce the time to 100usec per readreg by not writing the 32bit
sync preamble. The PHY normally should signal this ability in a bit in the
BMSR. Mine doesn't, but works without preamble (a comment in the linux
driver suggests that all except some very old cards work without
preamble).

See attached diffs.

harti
-- 
harti brandt, http://www.fokus.gmd.de/research/cc/cats/employees/hartmut.brandt/private
              brandt@fokus.gmd.de, brandt@fokus.fhg.de


[-- Attachment #2 --]
Index: if_xl.c
===================================================================
RCS file: /usr/ncvs/src/sys/pci/if_xl.c,v
retrieving revision 1.105
diff -u -r1.105 if_xl.c
--- if_xl.c	24 Aug 2002 00:02:03 -0000	1.105
+++ if_xl.c	16 Sep 2002 14:00:55 -0000
@@ -356,6 +356,16 @@
 	CSR_WRITE_2(sc, XL_W4_PHY_MGMT,			\
 		CSR_READ_2(sc, XL_W4_PHY_MGMT) & ~x)
 
+#define MII_SETCLR(x,y)					\
+	CSR_WRITE_2(sc, XL_W4_PHY_MGMT,			\
+		(CSR_READ_2(sc, XL_W4_PHY_MGMT) & ~y) | x)
+
+static __inline void
+xl_mii_delay(struct xl_softc *sc, u_int addr)
+{
+	CSR_READ_4(sc, addr);
+}
+
 /*
  * Sync the PHYs by setting data bit and strobing the clock 32 times.
  */
@@ -370,9 +380,9 @@
 
 	for (i = 0; i < 32; i++) {
 		MII_SET(XL_MII_CLK);
-		DELAY(1);
+		xl_mii_delay(sc, XL_W4_PHY_MGMT);
 		MII_CLR(XL_MII_CLK);
-		DELAY(1);
+		xl_mii_delay(sc, XL_W4_PHY_MGMT);
 	}
 
 	return;
@@ -390,18 +400,18 @@
 	int			i;
 
 	XL_SEL_WIN(4);
-	MII_CLR(XL_MII_CLK);
+	/* XXX MII_CLR(XL_MII_CLK); */
 
+	/* XXX could join the MII_SET/CLR of data with the CLR of the clock */
 	for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
                 if (bits & i) {
-			MII_SET(XL_MII_DATA);
+			MII_SETCLR(XL_MII_DATA, XL_MII_CLK);
                 } else {
-			MII_CLR(XL_MII_DATA);
+			MII_CLR((XL_MII_DATA | XL_MII_CLK));
                 }
-		DELAY(1);
-		MII_CLR(XL_MII_CLK);
-		DELAY(1);
+		xl_mii_delay(sc, XL_W4_PHY_MGMT);
 		MII_SET(XL_MII_CLK);
+		xl_mii_delay(sc, XL_W4_PHY_MGMT);
 	}
 }
 
@@ -433,11 +443,6 @@
 	XL_SEL_WIN(4);
 
 	CSR_WRITE_2(sc, XL_W4_PHY_MGMT, 0);
-	/*
- 	 * Turn on data xmit.
-	 */
-	MII_SET(XL_MII_DIR);
-
 	xl_mii_sync(sc);
 
 	/*
@@ -448,20 +453,20 @@
 	xl_mii_send(sc, frame->mii_phyaddr, 5);
 	xl_mii_send(sc, frame->mii_regaddr, 5);
 
-	/* Idle bit */
-	MII_CLR((XL_MII_CLK|XL_MII_DATA));
-	DELAY(1);
-	MII_SET(XL_MII_CLK);
-	DELAY(1);
-
 	/* Turn off xmit. */
 	MII_CLR(XL_MII_DIR);
 
+	/* turnaround */
+	MII_CLR((XL_MII_CLK|XL_MII_DATA));
+	xl_mii_delay(sc, XL_W4_PHY_MGMT);
+	MII_SET(XL_MII_CLK);
+	xl_mii_delay(sc, XL_W4_PHY_MGMT);
+
 	/* Check for ack */
 	MII_CLR(XL_MII_CLK);
-	DELAY(1);
+	xl_mii_delay(sc, XL_W4_PHY_MGMT);
 	MII_SET(XL_MII_CLK);
-	DELAY(1);
+	xl_mii_delay(sc, XL_W4_PHY_MGMT);
 	ack = CSR_READ_2(sc, XL_W4_PHY_MGMT) & XL_MII_DATA;
 
 	/*
@@ -471,31 +476,29 @@
 	if (ack) {
 		for(i = 0; i < 16; i++) {
 			MII_CLR(XL_MII_CLK);
-			DELAY(1);
+			xl_mii_delay(sc, XL_W4_PHY_MGMT);
 			MII_SET(XL_MII_CLK);
-			DELAY(1);
+			xl_mii_delay(sc, XL_W4_PHY_MGMT);
 		}
 		goto fail;
 	}
 
 	for (i = 0x8000; i; i >>= 1) {
 		MII_CLR(XL_MII_CLK);
-		DELAY(1);
-		if (!ack) {
-			if (CSR_READ_2(sc, XL_W4_PHY_MGMT) & XL_MII_DATA)
-				frame->mii_data |= i;
-			DELAY(1);
-		}
+		xl_mii_delay(sc, XL_W4_PHY_MGMT);
+		if (CSR_READ_2(sc, XL_W4_PHY_MGMT) & XL_MII_DATA)
+			frame->mii_data |= i;
 		MII_SET(XL_MII_CLK);
-		DELAY(1);
+		xl_mii_delay(sc, XL_W4_PHY_MGMT);
 	}
 
 fail:
 
+	/* Idle bit */
 	MII_CLR(XL_MII_CLK);
-	DELAY(1);
+	xl_mii_delay(sc, XL_W4_PHY_MGMT);
 	MII_SET(XL_MII_CLK);
-	DELAY(1);
+	xl_mii_delay(sc, XL_W4_PHY_MGMT);
 
 	XL_UNLOCK(sc);
 
@@ -544,9 +547,9 @@
 
 	/* Idle bit. */
 	MII_SET(XL_MII_CLK);
-	DELAY(1);
+	xl_mii_delay(sc, XL_W4_PHY_MGMT);
 	MII_CLR(XL_MII_CLK);
-	DELAY(1);
+	xl_mii_delay(sc, XL_W4_PHY_MGMT);
 
 	/*
 	 * Turn off xmit.

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