When executing header code (which contains U-Boot SPL in most cases),
wait 10s after every non-xmodem character received (i.e. printed by
U-Boot SPL) before timing out.

Sometimes DDR training, which runs in SPL, may be slow.

Signed-off-by: Marek Behún <marek.be...@nic.cz>
---
 tools/kwboot.c | 44 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 41 insertions(+), 3 deletions(-)

diff --git a/tools/kwboot.c b/tools/kwboot.c
index 2e16db83fa..0e60cc8a70 100644
--- a/tools/kwboot.c
+++ b/tools/kwboot.c
@@ -24,6 +24,7 @@
 #include <unistd.h>
 #include <stdint.h>
 #include <termios.h>
+#include <time.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 
@@ -68,6 +69,7 @@ struct kwboot_block {
 } __packed;
 
 #define KWBOOT_BLK_RSP_TIMEO 1000 /* ms */
+#define KWBOOT_HDR_RSP_TIMEO 10000 /* ms */
 
 static int kwboot_verbose;
 
@@ -381,12 +383,35 @@ _is_xm_reply(char c)
        return c == ACK || c == NAK || c == CAN;
 }
 
+static uint64_t
+_now(void)
+{
+       struct timespec ts;
+
+       if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
+               static int err_print;
+
+               if (!err_print) {
+                       perror("clock_gettime() does not work");
+                       err_print = 1;
+               }
+
+               /* this will just make the timeout not work */
+               return -1ULL;
+       }
+
+       return ts.tv_sec * 1000 + (ts.tv_nsec + 500000) / 1000000;
+}
+
 static int
 kwboot_xm_sendblock(int fd, struct kwboot_block *block, int allow_non_xm,
                    int *done_print)
 {
+       int recv_timeo = allow_non_xm ? KWBOOT_HDR_RSP_TIMEO : blk_rsp_timeo;
        int non_xm_print = 0;
+       uint64_t timeout = 0;
        int rc, retries;
+       int err;
        char c;
 
        *done_print = 0;
@@ -404,14 +429,22 @@ kwboot_xm_sendblock(int fd, struct kwboot_block *block, 
int allow_non_xm,
                }
 
                do {
-                       rc = kwboot_tty_recv(fd, &c, 1, blk_rsp_timeo);
+                       err = 0;
+                       rc = kwboot_tty_recv(fd, &c, 1, recv_timeo);
                        if (rc) {
-                               if (errno != ETIMEDOUT)
+                               if (errno != ETIMEDOUT) {
                                        return rc;
-                               c = NAK;
+                               } else if (timeout && timeout < _now()) {
+                                       errno = ETIMEDOUT;
+                                       return -1;
+                               } else {
+                                       err = errno;
+                                       c = NAK;
+                               }
                        }
 
                        if (!_is_xm_reply(c) && allow_non_xm) {
+                               timeout = _now() + recv_timeo;
                                putchar(c);
                                fflush(stdout);
                                non_xm_print = 1;
@@ -425,6 +458,11 @@ kwboot_xm_sendblock(int fd, struct kwboot_block *block, 
int allow_non_xm,
        if (non_xm_print)
                kwboot_printv("\n");
 
+       if (err) {
+               errno = err;
+               return -1;
+       }
+
        rc = -1;
 
        switch (c) {
-- 
2.31.1

Reply via email to