Allow myusec_calibrate_delay() to indicate errors and abort
in cli_classic if that happens.

Signed-off-by: Stefan Tauner <stefan.tau...@alumni.tuwien.ac.at>
---
 cli_classic.c |  6 +++++-
 programmer.h  |  2 +-
 udelay.c      | 22 ++++++++++++++--------
 3 files changed, 20 insertions(+), 10 deletions(-)
 
Roxfan on IRC had major problems getting flashrom to even start because
of some hardware-related timing problems. Without this patch his hardware
would (almost?) endlessly loop during timer calibration. This patch
aborts instead after a while and should not trigger any regressions.

One can test it by overriding the gettimeofday results in measure_delay()
by adding following assignments:
        start.tv_sec = 0;
        end.tv_sec = 0;
        start.tv_usec = 0;
        end.tv_usec = 0;

diff --git a/cli_classic.c b/cli_classic.c
index a2c2014..4a68f0b 100644
--- a/cli_classic.c
+++ b/cli_classic.c
@@ -414,7 +414,11 @@ int main(int argc, char *argv[])
        }
 
        /* FIXME: Delay calibration should happen in programmer code. */
-       myusec_calibrate_delay();
+       if (myusec_calibrate_delay() != 0) {
+               msg_perr("Error: Custom timer calibration failed.\n");
+               ret = 1;
+               goto out_shutdown;
+       }
 
        if (programmer_init(prog, pparam)) {
                msg_perr("Error: Programmer initialization failed.\n");
diff --git a/programmer.h b/programmer.h
index bd8e98d..b39fba4 100644
--- a/programmer.h
+++ b/programmer.h
@@ -268,8 +268,8 @@ extern const struct board_info laptops_known[];
 #endif
 
 /* udelay.c */
+int myusec_calibrate_delay(void);
 void myusec_delay(unsigned int usecs);
-void myusec_calibrate_delay(void);
 void internal_sleep(unsigned int usecs);
 void internal_delay(unsigned int usecs);
 
diff --git a/udelay.c b/udelay.c
index 7c6961d..3562268 100644
--- a/udelay.c
+++ b/udelay.c
@@ -85,7 +85,7 @@ static unsigned long measure_delay(unsigned int usecs)
        return timeusec;
 }
 
-void myusec_calibrate_delay(void)
+int myusec_calibrate_delay(void)
 {
        unsigned long count = 1000;
        unsigned long timeusec, resolution;
@@ -106,16 +106,21 @@ recalibrate:
                if (timeusec > 1000000 / 4)
                        break;
                if (count >= ULONG_MAX / 2) {
-                       msg_pinfo("timer loop overflow, reduced precision. ");
+                       msg_pwarn("timer loop overflow (count=%lu, micro=%lu, 
timeusec=%lu), reduced precision.\n",
+                                 count, micro, timeusec);
                        break;
                }
                count *= 2;
        }
        tries ++;
 
-       /* Avoid division by zero, but in that case the loop is shot anyway. */
-       if (!timeusec)
-               timeusec = 1;
+       /* Something is completely wrong. Avoid a possible endless loop and 
fall back to internal_delay(). */
+       if (timeusec == 0) {
+               micro = 0;
+               msg_pwarn("Timing measurement seems to be broken.\n"
+                         "Falling back to possibly insufficient timing 
sources!\n");
+               return 1;
+       }
        
        /* Compute rounded up number of loops per microsecond. */
        micro = (count * micro) / timeusec + 1;
@@ -168,6 +173,7 @@ recalibrate:
        msg_pdbg("%ld myus = %ld us, ", resolution * 4, timeusec);
 
        msg_pinfo("OK.\n");
+       return 0;
 }
 
 /* Not very precise sleep. */
@@ -187,7 +193,7 @@ void internal_sleep(unsigned int usecs)
 void internal_delay(unsigned int usecs)
 {
        /* If the delay is >1 s, use internal_sleep because timing does not 
need to be so precise. */
-       if (usecs > 1000000) {
+       if (micro == 0 || usecs > 1000000) {
                internal_sleep(usecs);
        } else {
                myusec_delay(usecs);
@@ -197,9 +203,9 @@ void internal_delay(unsigned int usecs)
 #else 
 #include <libpayload.h>
 
-void myusec_calibrate_delay(void)
+int myusec_calibrate_delay(void)
 {
-       get_cpu_speed();
+       return get_cpu_speed() == 0; // Return 1 on errors, i.e. if 
get_cpu_speed() returns 0
 }
 
 void internal_delay(unsigned int usecs)
-- 
Kind regards, Stefan Tauner


_______________________________________________
flashrom mailing list
flashrom@flashrom.org
https://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to