Subject: Re: IP1000 gigabit nic driver

From: David Vrabel <[email-masked]>
Date: Mon, 01 May 2006 12:32:40 +0100

David Vrabel wrote:
> 
>     - something (PHY reset/auto negotiation?) takes 2-3 seconds and
>       appears to be done with interrupts disabled.

It was clocking the MII management interface (MDC) at 500 Hz so each PHY
register access took some 130 ms, and many registers accesses were being
done on initialization. According to the datasheet, the maximum
frequency for MDC is 2.5 MHz.  Delays have been adjusted accordingly.

David Vrabel
Reduce delays when reading/writing the PHY registers so we clock the
MII management interface at 2.5 MHz (the maximum according to the
datasheet) instead of 500 Hz.

Signed-off-by: David Vrabel <[email-masked]>

Index: linux-source-2.6.16/drivers/net/ipg.c
===================================================================
--- linux-source-2.6.16.orig/drivers/net/ipg.c	2006-05-01 11:52:32.555800238 +0100
+++ linux-source-2.6.16/drivers/net/ipg.c	2006-05-01 12:08:45.316188064 +0100
@@ -176,13 +176,13 @@
 		 (IPG_PC_MGMTCLK_LO | (IPG_PC_MGMTDATA & 0) | IPG_PC_MGMTDIR |
 		  phyctrlpolarity), ioaddr + IPG_PHYCTRL);
 
-	mdelay(IPG_PC_PHYCTRLWAIT);
+	ndelay(IPG_PC_PHYCTRLWAIT_NS);
 
 	iowrite8(IPG_PC_RSVD_MASK &
 		 (IPG_PC_MGMTCLK_HI | (IPG_PC_MGMTDATA & 0) | IPG_PC_MGMTDIR |
 		  phyctrlpolarity), ioaddr + IPG_PHYCTRL);
 
-	mdelay(IPG_PC_PHYCTRLWAIT);
+	ndelay(IPG_PC_PHYCTRLWAIT_NS);
 }
 
 static void send_end(void __iomem * ioaddr, u8 phyctrlpolarity)
@@ -198,7 +198,7 @@
 	iowrite8(IPG_PC_RSVD_MASK & (IPG_PC_MGMTCLK_LO | phyctrlpolarity),
 		 ioaddr + IPG_PHYCTRL);
 
-	mdelay(IPG_PC_PHYCTRLWAIT);
+	ndelay(IPG_PC_PHYCTRLWAIT_NS);
 
 	bit_data =
 	    ((ioread8(ioaddr + IPG_PHYCTRL) & IPG_PC_MGMTDATA) >> 1) & 1;
@@ -206,7 +206,7 @@
 	iowrite8(IPG_PC_RSVD_MASK & (IPG_PC_MGMTCLK_HI | phyctrlpolarity),
 		 ioaddr + IPG_PHYCTRL);
 
-	mdelay(IPG_PC_PHYCTRLWAIT);
+	ndelay(IPG_PC_PHYCTRLWAIT_NS);
 	return bit_data;
 }
 
@@ -290,14 +290,14 @@
 				  (IPG_PC_MGMTDATA & databit) | IPG_PC_MGMTDIR |
 				  phyctrlpolarity), ioaddr + IPG_PHYCTRL);
 
-			mdelay(IPG_PC_PHYCTRLWAIT);
+			ndelay(IPG_PC_PHYCTRLWAIT_NS);
 
 			iowrite8(IPG_PC_RSVD_MASK &
 				 (IPG_PC_MGMTCLK_HI |
 				  (IPG_PC_MGMTDATA & databit) | IPG_PC_MGMTDIR |
 				  phyctrlpolarity), ioaddr + IPG_PHYCTRL);
 
-			mdelay(IPG_PC_PHYCTRLWAIT);
+			ndelay(IPG_PC_PHYCTRLWAIT_NS);
 		}
 
 	send_three_state(ioaddr, phyctrlpolarity);
@@ -403,14 +403,14 @@
 				  (IPG_PC_MGMTDATA & databit) | IPG_PC_MGMTDIR |
 				  phyctrlpolarity), ioaddr + IPG_PHYCTRL);
 
-			mdelay(IPG_PC_PHYCTRLWAIT);
+			ndelay(IPG_PC_PHYCTRLWAIT_NS);
 
 			iowrite8(IPG_PC_RSVD_MASK &
 				 (IPG_PC_MGMTCLK_HI |
 				  (IPG_PC_MGMTDATA & databit) | IPG_PC_MGMTDIR |
 				  phyctrlpolarity), ioaddr + IPG_PHYCTRL);
 
-			mdelay(IPG_PC_PHYCTRLWAIT);
+			ndelay(IPG_PC_PHYCTRLWAIT_NS);
 		}
 
 	/* The last cycle is a tri-state, so read from the PHY.
@@ -421,7 +421,7 @@
 				 (IPG_PC_MGMTCLK_LO | phyctrlpolarity),
 				 ioaddr + IPG_PHYCTRL);
 
-			mdelay(IPG_PC_PHYCTRLWAIT);
+			ndelay(IPG_PC_PHYCTRLWAIT_NS);
 
 			field[j] |= ((ioread8(ioaddr + IPG_PHYCTRL) &
 				      IPG_PC_MGMTDATA) >> 1)
@@ -431,7 +431,7 @@
 				 (IPG_PC_MGMTCLK_HI | phyctrlpolarity),
 				 ioaddr + IPG_PHYCTRL);
 
-			mdelay(IPG_PC_PHYCTRLWAIT);
+			ndelay(IPG_PC_PHYCTRLWAIT_NS);
 
 		}
 }
Index: linux-source-2.6.16/drivers/net/ipg.h
===================================================================
--- linux-source-2.6.16.orig/drivers/net/ipg.h	2006-05-01 12:08:58.343035854 +0100
+++ linux-source-2.6.16/drivers/net/ipg.h	2006-05-01 12:09:37.282602113 +0100
@@ -672,10 +672,10 @@
 /* Number of IPG_AC_RESETWAIT timeperiods before declaring timeout. */
 #define         IPG_AC_RESET_TIMEOUT         0x0A
 
-/* Minimum number of miliseconds used to toggle MDC clock during
+/* Minimum number of nanoseconds used to toggle MDC clock during
  * MII/GMII register access.
  */
-#define         IPG_PC_PHYCTRLWAIT           0x01
+#define		IPG_PC_PHYCTRLWAIT_NS		200
 
 #define		IPG_TFDLIST_LENGTH		0x100