From patchwork Sat Jul 30 19:56:53 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Tauner X-Patchwork-Id: 654285 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail.coreboot.org (mail.coreboot.org [80.81.252.135]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3s1xHq5YM9z9ssM for ; Sun, 31 Jul 2016 05:59:02 +1000 (AEST) Received: from [127.0.0.1] (helo=ra.coresystems.de) by mail.coreboot.org with esmtp (Exim 4.86_2) (envelope-from ) id 1bTaOj-0006AD-80; Sat, 30 Jul 2016 21:58:13 +0200 Received: from mail2.student.tuwien.ac.at ([193.170.74.22]) by mail.coreboot.org with esmtps (TLSv1:DHE-RSA-AES256-SHA:256) (Exim 4.86_2) (envelope-from ) id 1bTaOU-00069p-JG for flashrom@flashrom.org; Sat, 30 Jul 2016 21:58:11 +0200 Received: from localhost.localdomain (chello080109083031.10.15.vie.surfer.at [80.109.83.31]) (authenticated bits=0) by mail2.student.tuwien.ac.at (8.13.8/8.13.8) with ESMTP id u6UJvp0P001117 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NO); Sat, 30 Jul 2016 21:57:52 +0200 From: Stefan Tauner To: flashrom@flashrom.org Date: Sat, 30 Jul 2016 21:56:53 +0200 Message-Id: <20160730195653.11008-1-stefan.tauner@alumni.tuwien.ac.at> X-Mailer: git-send-email 2.9.0.rc2.8.ga28705d X-Spam-Score: -0.1 (/) Subject: [flashrom] [PATCH] Work around very broken timers. X-BeenThere: flashrom@flashrom.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: flashrom discussion and development mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: flashrom-bounces@flashrom.org Sender: "flashrom" X-Duff: Orig. Duff, Duff Lite, Duff Dry, Duff Dark, Raspberry Duff, Lady Duff, Red Duff, Tartar Control Duff Allow myusec_calibrate_delay() to indicate errors and abort in cli_classic if that happens. Signed-off-by: Stefan Tauner --- 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 -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)