Re: Synology PPCBoot SK98 network bug fix

Julian Coleman <[email protected]> Mon, 30 May 2011 21:38:48 +0100
Newsgroups gmane.os.netbsd.ports.sandpoint
Message-ID <[email protected]>
Hi,

> Yes, that could be the problem, indeed.
> 
> Even if you didn't tell your routers/switches via IGMP that you want
> to receive multicast packets, you are receiving them anyway, because the
> NIC is in promiscious mode? :|

It appears that it almost is ;-)  I tried zeroing the multicast hash list,
and that didn't make any difference that I could see.  However, I've left
it in, as it didn't seem to cause any harm.

> You really must have a lot of traffic on your net.
> 
> I admit that my home network is quite calm. Three or four clients
> maximum. And usually no traffic at all.

There are currently 5 machines running, and 2 switches, and the Internet
connection is via a router.  This means that on any network segment there
are at least 2 multicasts or broadcasts per second (IGMP and spanning tree)
plus any other *cast traffic.  The NAS is the only device on a switch port,
so there isn't any other unicast traffic.  I think that we should be able to
cope with that ;-)

> The problem you describe would affect all network drivers in altboot,
> not just skg.c. No driver uses more than two descriptors.
> 
> Probably it is better to define in the documentation that you need to
> provide a network with low traffic for installation.

Hmm, I think that I'd prefer to increase the number of receive descriptors.
I increased it to 16 in skg.c and had no problems loading the kernel via
NFS.  Using 8 seems to be OK now too - I did have failures before, but that
was with the extra debug printout enabled.

I've attached a patch.  I don't think that it will break anything.  It:

  o makes the number of transmit and receive descriptors into #define's,
  o moves the start address of the transmit ram buffers because there are
    more receive ram buffers
  o iterates over the number of descriptors when setting them up
  o checks all receive descriptors for the first one with CTL_OWN
  o zero's the multicast filters

The code in skg_send() still assumes 2 transmit descriptors.  It might be
better to fix that too?

Thanks,

J

-- 
  My other computer also runs NetBSD    /        Sailing at Newbiggin
        http://www.netbsd.org/        /   http://www.newbigginsailingclub.org/
altboot-patch.text (text/plain, 4.8 KB)
Index: skg.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sandpoint/stand/altboot/skg.c,v
retrieving revision 1.3
diff -u -r1.3 skg.c
--- skg.c	29 May 2011 18:06:45 -0000	1.3
+++ skg.c	30 May 2011 20:23:56 -0000
@@ -153,6 +153,10 @@
 #define  GPCR_RXEN		0x0800
 #define YUKON_SA1		0x281c
 #define YUKON_SA2		0x2828
+#define YUKON_MC1		0x2834
+#define YUKON_MC2		0x2838
+#define YUKON_MC3		0x283c
+#define YUKON_MC4		0x2840
 #define YUKON_SMICR		0x2880
 #define  SMICR_PHYAD(x)		(((x) & 0x1f) << 11)
 #define  SMICR_REGAD(x)		(((x) & 0x1f) << 6)
@@ -173,11 +177,13 @@
 
 #define FRAMESIZE	1536
 
+#define NUM_TXDESC	2
+#define NUM_RXDESC	8
 struct local {
-	struct desc txd[2];
-	struct desc rxd[2];
-	uint8_t rxstore[2][FRAMESIZE];
-	unsigned csr, rx, tx, phy;
+	struct desc txd[NUM_TXDESC];
+	struct desc rxd[NUM_RXDESC];
+	uint8_t rxstore[NUM_RXDESC][FRAMESIZE];
+	unsigned csr, /*rx, */tx, phy;
 	uint16_t pssr, anlpar;
 };
 
@@ -246,6 +252,12 @@
 		CSR_WRITE_2(l, YUKON_SA1 + i * 4,
 		    (en[i * 2] << 8) | en[i * 2 + 1]);
 
+	/* zero multicast filters */
+	CSR_WRITE_2(l, YUKON_MC1, 0);
+	CSR_WRITE_2(l, YUKON_MC2, 0);
+	CSR_WRITE_2(l, YUKON_MC3, 0);
+	CSR_WRITE_2(l, YUKON_MC4, 0);
+
 	/* configure RX and TX MAC FIFO */
 	CSR_WRITE_1(l, SK_RXMF1_CTRL_TEST, RFCTL_RESET_CLEAR);
 	CSR_WRITE_4(l, SK_RXMF1_CTRL_TEST, RFCTL_OPERATION_ON);
@@ -274,29 +286,31 @@
 	CSR_WRITE_4(l, SK_RXRB1_START, 0);
 	CSR_WRITE_4(l, SK_RXRB1_WR_PTR, 0);
 	CSR_WRITE_4(l, SK_RXRB1_RD_PTR, 0);
-	CSR_WRITE_4(l, SK_RXRB1_END, 0xfff);
+	CSR_WRITE_4(l, SK_RXRB1_END, 0x3fff);
 	CSR_WRITE_4(l, SK_RXRB1_CTLTST, RBCTL_ON);
 	CSR_WRITE_4(l, SK_TXRBS1_CTLTST, RBCTL_UNRESET);
 	CSR_WRITE_4(l, SK_TXRBS1_CTLTST, RBCTL_STORENFWD_ON);
-	CSR_WRITE_4(l, SK_TXRBS1_START, 0x1000);
-	CSR_WRITE_4(l, SK_TXRBS1_WR_PTR, 0x1000);
-	CSR_WRITE_4(l, SK_TXRBS1_RD_PTR, 0x1000);
-	CSR_WRITE_4(l, SK_TXRBS1_END, 0x1fff);
+	CSR_WRITE_4(l, SK_TXRBS1_START, 0x4000);
+	CSR_WRITE_4(l, SK_TXRBS1_WR_PTR, 0x4000);
+	CSR_WRITE_4(l, SK_TXRBS1_RD_PTR, 0x4000);
+	CSR_WRITE_4(l, SK_TXRBS1_END, 0x4fff);
 	CSR_WRITE_4(l, SK_TXRBS1_CTLTST, RBCTL_ON);
 
 	/* setup descriptors and BMU */
 	CSR_WRITE_1(l, SK_TXAR1_COUNTERCTL, TXARCTL_ON|TXARCTL_FSYNC_ON);
 
 	txd = &l->txd[0];
-	txd[0].xd1 = htole32(VTOPHYS(&txd[1]));
-	txd[1].xd1 = htole32(VTOPHYS(&txd[0]));
+	for (i = 0; i < NUM_TXDESC; i ++)
+		txd[i].xd1 = htole32(VTOPHYS(&txd[(i + 1) & ~NUM_TXDESC]));
 	rxd = &l->rxd[0];
-	rxd[0].xd0 = htole32(FRAMESIZE|CTL_DEFOPC|CTL_LS|CTL_FS|CTL_OWN);
-	rxd[0].xd1 = htole32(VTOPHYS(&rxd[1]));
-	rxd[0].xd2 = htole32(VTOPHYS(l->rxstore[0]));
-	rxd[1].xd0 = htole32(FRAMESIZE|CTL_DEFOPC|CTL_LS|CTL_FS|CTL_OWN);
-	rxd[1].xd1 = htole32(VTOPHYS(&rxd[0]));
-	rxd[1].xd2 = htole32(VTOPHYS(l->rxstore[1]));
+	
+	for (i = 0; i < NUM_RXDESC; i ++) {
+		rxd[i].xd0 =
+		    htole32(FRAMESIZE|CTL_DEFOPC|CTL_LS|CTL_FS|CTL_OWN);
+		rxd[i].xd1 = htole32(VTOPHYS(&rxd[(i + 1) & ~NUM_RXDESC]));
+		rxd[i].xd2 =
+		    htole32(VTOPHYS(l->rxstore[i]));
+	}
 	wbinv(l, sizeof(struct local));
 
 	CSR_WRITE_4(l, SK_RXQ1_BMU_CSR,
@@ -331,6 +345,13 @@
 	volatile struct desc *txd;
 	unsigned loop;
 
+	DPRINTF(("sending\n"));
+	DPRINTF((">> "));
+	for (loop = 0; loop < 14; loop++) {
+		DPRINTF(("%02x ", buf[loop]));
+	}
+	DPRINTF(("\n"));
+
 	wbinv(buf, len);
 	txd = &l->txd[l->tx];
 	txd->xd2 = htole32(VTOPHYS(buf));
@@ -356,41 +377,46 @@
 {
 	struct local *l = dev;
 	volatile struct desc *rxd;
-	unsigned bound, ctl, rxstat, len;
+	unsigned loop, bound, ctl, rxstat, len;
 	uint8_t *ptr;
 
 	bound = 1000 * timo;
-#if 0
-printf("recving with %u sec. timeout\n", timo);
-#endif
+	DPRINTF(("recving with %u sec. timeout\n", timo));
   again:
-	rxd = &l->rxd[l->rx];
 	do {
-		inv(rxd, sizeof(struct desc));
-		ctl = le32toh(rxd->xd0);
-		if ((ctl & CTL_OWN) == 0)
-			goto gotone;
+		for (loop = 0; loop < NUM_RXDESC; loop++) {
+			rxd = &l->rxd[loop];
+			inv(rxd, sizeof(struct desc));
+			ctl = le32toh(rxd->xd0);
+			if ((ctl & CTL_OWN) == 0)
+				goto gotone;
+		}
 		DELAY(1000);	/* 1 milli second */
 	} while (--bound > 0);
 	errno = 0;
 	return -1;
   gotone:
   	rxstat = le32toh(rxd->xd4);
+	DPRINTF(("Got one rxd[%d] : rxstat = %08x\n", loop, rxstat));
 	if ((rxstat & RXSTAT_RXOK) == 0) {
 		rxd->xd0 = htole32(FRAMESIZE|CTL_DEFOPC|CTL_LS|CTL_FS|CTL_OWN);
 		wbinv(rxd, sizeof(struct desc));
-		l->rx ^= 1;
 		goto again;
 	}
+	DPRINTF(("Parsing : ctl = %08x\n", ctl));
 	len = ctl & FRAMEMASK;
 	if (len > maxlen)
 		len = maxlen;
-	ptr = l->rxstore[l->rx];
+	ptr = l->rxstore[loop];
 	inv(ptr, len);
 	memcpy(buf, ptr, len);
+	DPRINTF((">> "));
+	for (loop = 0; loop < 14; loop++) {
+		DPRINTF(("%02x ", buf[loop]));
+	}
+	DPRINTF(("\n"));
 	rxd->xd0 = htole32(FRAMESIZE|CTL_DEFOPC|CTL_LS|CTL_FS|CTL_OWN);
 	wbinv(rxd, sizeof(struct desc));
-	l->rx ^= 1;
 	return len;
 }