[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: Hangs with 100baseTX, RedHat 7.1, kernel 2.4.x and AlphaPC 164



On Thu, Oct 04, 2001 at 06:26:10PM -0400, Jay Estabrook wrote:
> I think maybe Ivan has some patches that do a better job in that area,
> and I know he's going to submit them soon. Maybe he'll post them here
> for some additional testing... :-) :-)

Sure, especially because my latest patch doesn't work on a pc164,
as Richard reported. :-(
So I would return to my previous thought - compare the measured frequency
with one reported in the hwrpb and return failure if we see twofold or higher
difference. Also emergency timeout added, as you suggested.

Ivan.

--- 2.4.10/arch/alpha/kernel/time.c	Fri Oct  5 13:43:01 2001
+++ linux/arch/alpha/kernel/time.c	Fri Oct  5 13:53:20 2001
@@ -170,28 +170,28 @@ common_init_rtc(void)
 }
 
 /*
- * Calibrate CPU clock using legacy 8254 timer/counter. Stolen from
- * arch/i386/time.c.
+ * Calibrate CPU clock using legacy 8254 programmable interval timer.
+ * Based on arch/i386/time.c.
  */
 
-#define CALIBRATE_LATCH	(52 * LATCH)
-#define CALIBRATE_TIME	(52 * 1000020 / HZ)
+#define CALIBRATE_LATCH	0xffff
+#define TIMEOUT_COUNT	0x100000
 
 static unsigned long __init
-calibrate_cc_with_pic(void)
+calibrate_cc_with_pit(void)
 {
-	int cc;
-	unsigned long count = 0;
+	int cc, count = 0;
+	unsigned long freq, hwrpbfreq = hwrpb->cycle_freq;
 
 	/* Set the Gate high, disable speaker */
 	outb((inb(0x61) & ~0x02) | 0x01, 0x61);
 
 	/*
-	 * Now let's take care of CTC channel 2
+	 * Now let's take care of PIT channel 2
 	 *
-	 * Set the Gate high, program CTC channel 2 for mode 0,
+	 * Set the Gate high, program PIT channel 2 for mode 0,
 	 * (interrupt on terminal count mode), binary count,
-	 * load 5 * LATCH count, (LSB and MSB) to begin countdown.
+	 * load CALIBRATE_LATCH count (LSB and MSB) to begin countdown.
 	 */
 	outb(0xb0, 0x43);		/* binary, mode 0, LSB/MSB, Ch 2 */
 	outb(CALIBRATE_LATCH & 0xff, 0x42);	/* LSB of count */
@@ -200,29 +200,23 @@ calibrate_cc_with_pic(void)
 	cc = rpcc();
 	do {
 		count++;
-	} while ((inb(0x61) & 0x20) == 0);
+	} while (!(inb(0x61) & 0x20) && count < TIMEOUT_COUNT);
 	cc = rpcc() - cc;
 
-	/* Error: ECTCNEVERSET */
-	if (count <= 1)
-		goto bad_ctc;
-
-	/* Error: ECPUTOOFAST */
-	if (count >> 32)
-		goto bad_ctc;
-
-	/* Error: ECPUTOOSLOW */
-	if (cc <= CALIBRATE_TIME)
-		goto bad_ctc;
+	/* Error: EPITNEVERSET or ECPUTOOFAST */
+	if (count <= 1 || count == TIMEOUT_COUNT)
+		goto bad_pit;
+
+	freq = ((long)cc * CLOCK_TICK_RATE) / (CALIBRATE_LATCH + 1);
+
+	/* CPU cycle frequency reported in the hwrpb is often bogus.
+	   However, even in the worst case the difference shouldn't
+	   exceed 30-40%, so we can still use hwrpb value to validate
+	   the frequency we've found with PIT. */
+	if ((max(freq, hwrpbfreq) + 1) / (min(freq, hwrpbfreq) + 1) < 2)
+		return freq;
 
-	return ((long)cc * 1000000) / CALIBRATE_TIME;
-
-	/*
-	 * The CTC wasn't reliable: we got a hit on the very first read,
-	 * or the CPU was so fast/slow that the quotient wouldn't fit in
-	 * 32 bits..
-	 */
- bad_ctc:
+ bad_pit:
 	return 0;
 }
 
@@ -249,7 +243,7 @@ time_init(void)
 
 	/* Calibrate CPU clock -- attempt #1.  */
 	if (!est_cycle_freq)
-		est_cycle_freq = calibrate_cc_with_pic();
+		est_cycle_freq = calibrate_cc_with_pit();
 
 	cc1 = rpcc_after_update_in_progress();
 





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index] []