Port-sandpoint archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Synology PPCBoot SK98 network bug fix



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/
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;
 }
 


Home | Main Index | Thread Index | Old Index