Subject: port-sparc64/18451: CRC errors occur on tlp (100baseTX) of Netra X1
To: None <gnats-bugs@gnats.netbsd.org>
From: None <t-nkyma@tcp-ip.or.jp>
List: netbsd-bugs
Date: 09/29/2002 03:31:25
>Number:         18451
>Category:       port-sparc64
>Synopsis:       CRC errors occur on tlp (100baseTX) of Netra X1
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    port-sparc64-maintainer
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Sep 28 11:32:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Takeshi Nakayama
>Release:        NetBSD 1.6
>Organization:
Private
>Environment:
System: NetBSD nyx 1.6 NetBSD 1.6 (NYX32) #39: Fri Sep 27 18:42:10 JST 2002
 takeshi@nyx:/usr/src/sys/arch/sparc64/compile/NYX32 sparc64
Architecture: sparc
Machine: sparc64
>Description:
	CRC errors occur repeatedly while we set media to 100baseTX
	on tlp of Netra X1.
>How-To-Repeat:
	Apply a heavy load to tlp of Netra X1 (e.g. write a large
	file via samba).
>Fix:
	Davicom DM9102A (tlp of Netra X1) seems to have some issue.
	It needs to set appropriate value to PCI latency timer, but
	sparc64 firmware does not do it.

	There are two methods for solving this issue.

	First method:
	    Set the PCI latency timer in sys/dev/pci/if_tlp_pci.c.
	    if_dc.c of FreeBSD/OpenBSD is using this method.

	Second method:
	    Set an appropriate PCI latency timer value in MD part
	    of sparc64. FreeBSD/saprc64 takes this methods (in
	    sys/sparc64/pci/ofw_pci.c).

	The following patch is sample of the second method.

Index: pci_machdep.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sparc64/dev/pci_machdep.c,v
retrieving revision 1.32
diff -u -d -r1.32 pci_machdep.c
--- pci_machdep.c	2002/06/29 02:35:22	1.32
+++ pci_machdep.c	2002/09/16 04:20:15
@@ -373,6 +373,8 @@
 	pci_intr_handle_t *ihp;
 {
 	pcitag_t tag = pa->pa_tag;
+	pcireg_t bhlc, ic;
+	int val;
 	int interrupts;
 	int len, node = PCITAG_NODE(tag);
 	char devtype[30];
@@ -401,6 +403,22 @@
 				interrupts |= INTLEVENCODE(intrmap[len].in_lev);
 				break;
 			}
+	}
+
+	/*
+	 * Initialize the latency timer register for busmaster devices
+	 * to work properly.
+	 *   latency-timer = min-grant * bus-freq / 4  (from FreeBSD)
+	 */
+	ic = pci_conf_read(pa->pa_pc, tag, PCI_INTERRUPT_REG);
+	val = min(PCI_MIN_GNT(ic) * 33 / 4, 255);
+	if (val > 0) {
+		bhlc = pci_conf_read(pa->pa_pc, tag, PCI_BHLC_REG);
+		if (PCI_LATTIMER(bhlc) < val) {
+			bhlc &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
+			bhlc |= (val << PCI_LATTIMER_SHIFT);
+			pci_conf_write(pa->pa_pc, tag, PCI_BHLC_REG, bhlc);
+		}
 	}
 
 	/* XXXX -- we use the ino.  What if there is a valid IGN? */
>Release-Note:
>Audit-Trail:
>Unformatted: