[eepro100] Re: Integrated Pro/100 on Intel D815EEA - serious problem

Andrey Savochkin saw@saw.sw.com.sg
Tue, 20 Feb 2001 18:36:18 -0800


--dDRMvlgZJXvWKvBx
Content-Type: text/plain; charset=us-ascii

Hi,

On Tue, Feb 20, 2001 at 11:29:03PM +0100, Noll Janos wrote:
>  I've tried to get informed about this problem. Using Deja.com-s search, I've
> found that many people are having problems with the Intel D815EEA motherboard
> (which has an integrated ethernet card).
> 
>  The system seems to run "fine" until it gets some (not even too large) net
> load...
[snip]
> [...]
> eepro100: wait_for_cmd_done timeout!

It's interesting to know which command caused this timeout.
I debugged some similar problems with the attached patch.

Best regards
		Andrey

--dDRMvlgZJXvWKvBx
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff

--- versions/eepro100.c.R1.33	Fri May 26 19:33:47 2000
+++ patches/eepro100.c-testwait	Tue Jun 20 03:07:45 2000
@@ -363,19 +363,6 @@
 #define outl writel
 #endif
 
-/* How to wait for the command unit to accept a command.
-   Typically this takes 0 ticks. */
-static inline void wait_for_cmd_done(long cmd_ioaddr)
-{
-	int wait = 1000;
-	do   ;
-	while(inb(cmd_ioaddr) && --wait >= 0);
-#ifndef final_version
-	if (wait < 0)
-		printk(KERN_ALERT "eepro100: wait_for_cmd_done timeout!\n");
-#endif
-}
-
 /* Offsets to the various registers.
    All accesses need not be longword aligned. */
 enum speedo_offsets {
@@ -532,6 +519,7 @@
 	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
 	unsigned int flow_ctrl:1;			/* Use 802.3x flow control. */
 	unsigned int rx_bug:1;				/* Work around receiver hang errata. */
+	unsigned int dumpstat;				/* Last command was CUDumpStat. */
 	unsigned char default_port:8;		/* Last dev->if_port value. */
 	unsigned char rx_ring_state;		/* RX ring status flags. */
 	unsigned short phy[2];				/* PHY media interfaces available. */
@@ -1036,6 +1039,77 @@
 	return 0;
 }
 
+/* How to wait for the command unit to accept a command.
+   Typically this takes 0 ticks. */
+
+static int show_trace(int dummy)
+{
+	int i;
+	unsigned long *stack, addr, module_start, module_end;
+#define MODULE_RANGE (8*1024*1024)
+	printk("CPU:    %d\nEIP:    [<%08lx>]\n",
+		smp_processor_id(), (unsigned long)__builtin_return_address(0));
+	printk("Stack: ");
+	stack = (unsigned long *) &dummy;
+	for(i = 0; i < 24; i++) {
+		if (((long) stack & (THREAD_SIZE-1)) == 0)
+			break;
+		if (i && ((i % 8) == 0))
+			printk("\n       ");
+		printk("%08lx ", *stack++);
+	}
+	printk("\nCall Trace: ");
+	stack = (unsigned long *) &dummy;
+	i = 1;
+	module_start = PAGE_OFFSET + (max_mapnr << PAGE_SHIFT);
+	module_start = ((module_start + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1));
+	module_end = module_start + MODULE_RANGE;
+	while (((long) stack & (THREAD_SIZE-1)) != 0) {
+		extern char _stext, _etext;
+		addr = *stack++;
+		/*
+		 * If the address is either in the text segment of the
+		 * kernel, or in the region which contains vmalloc'ed
+		 * memory, it *may* be the address of a calling
+		 * routine; if so, print it so that someone tracing
+		 * down the cause of the crash will be able to figure
+		 * out the call path that was taken.
+		 */
+		if (((addr >= (unsigned long) &_stext) &&
+		     (addr <= (unsigned long) &_etext)) ||
+		    ((addr >= module_start) && (addr <= module_end))) {
+			if (i && ((i % 8) == 0))
+				printk("\n       ");
+			printk("[<%08lx>] ", addr);
+			i++;
+		}
+	}
+	return 0;
+}
+
+#if 0
+static void wait_for_cmd_done(long cmd_ioaddr)
+#endif
+#define wait_for_cmd_done(cmd_ioaddr) \
+do \
+{ \
+	int wait = 1000; \
+	do   ; \
+	while(inb(cmd_ioaddr) && --wait >= 0); \
+	if (wait < 0) { \
+		printk(KERN_ALERT "eepro100: wait_for_cmd_done timeout!\n"); \
+		/* DEBUG */ \
+		show_trace(0); \
+		printk(KERN_INFO \
+			   "eepro100: w-f-c-d-t, cmd=%04x, stat=%04x, %d.\n", \
+			   inw(cmd_ioaddr), inw(cmd_ioaddr + SCBStatus - SCBCmd), \
+			   sp->dumpstat); \
+	} else { \
+		sp->dumpstat = 0; \
+	} \
+} \
+while (0)
+
 /* Start the chip hardware after a full reset. */
 static void speedo_resume(struct net_device *dev)
 {
@@ -1934,6 +1999,7 @@
 			spin_lock_irqsave(&sp->lock, flags);
 			wait_for_cmd_done(ioaddr + SCBCmd);
 			outb(CUDumpStats, ioaddr + SCBCmd);
+			sp->dumpstat = 2;
 			spin_unlock_irqrestore(&sp->lock, flags);
 		}
 	}

--dDRMvlgZJXvWKvBx--