From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 99C25C433EF for ; Wed, 2 Mar 2022 10:53:25 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id E476E83C7F; Wed, 2 Mar 2022 11:53:06 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="hgVJ8h7S"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 50DAE83C8F; Wed, 2 Mar 2022 11:53:00 +0100 (CET) Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 9530A83C64 for ; Wed, 2 Mar 2022 11:52:47 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=pali@kernel.org Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id EE0F261741; Wed, 2 Mar 2022 10:52:45 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6F8FEC004E1; Wed, 2 Mar 2022 10:52:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1646218365; bh=Mqci0ifLhDH6V/9wjhFuQOJWR9r9AgISBD6bNyzrPOU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hgVJ8h7SNfw5OhegM1szhIsxz3FItFmiMsK6sJ6Z5ZEjmkkbcK7D1LdgElwRgDXC5 JO4x1RX5F3Cj9NZKEKXH54hdsiSXmvxFEpZmq60lJH0tvRZ3Rc9jTWxE6oQ8pKX3KZ 8zMkVDXfHTuaQjOvtZeNgNH+U2pA1gfKgdmBC5G+ofcyjUqhqmcNKPLq7iP4ZpYdJ9 cYf5M9has002vbvmZQCSMJNhAedtq4JaXu9UKvX/jQUDe3uYBSB3oxtov2OX7SLfK6 nTqzhflPI+7mH8dBcveUplkGJdMee+4xV36XPOX2vbnM0nxbauJS8llwns3c639VrM n6Pv5mqWfUDnA== Received: by pali.im (Postfix) id 26294677; Wed, 2 Mar 2022 11:52:45 +0100 (CET) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Stefan Roese , =?UTF-8?q?Marek=20Beh=C3=BAn?= , Tony Dinh Cc: u-boot@lists.denx.de Subject: [PATCH u-boot-marvell 04/10] tools: kwboot: Use separate thread for sending boot message pattern Date: Wed, 2 Mar 2022 11:49:21 +0100 Message-Id: <20220302104927.18607-5-pali@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20220302104927.18607-1-pali@kernel.org> References: <20220302104927.18607-1-pali@kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.5 at phobos.denx.de X-Virus-Status: Clean After BootROM successfully detects boot message pattern on UART it waits until host stop sending data on UART. For example Armada 385 BootROM requires that host does not send anything on UART at least 24 ms. If host is still sending something then BootROM waits (possibly infinitely). BootROM successfully detects boot message pattern if it receives it in small period of time after power on. So to ensure that host put BootROM into UART boot mode, host must send continuous stream of boot message pattern with a small gap (for A385 at least 24 ms) after series of pattern. But this gap cannot be too often or too long to ensure that it does not cover whole BootROM time window when it is detecting for boot message pattern. Therefore it is needed to do following steps in cycle without any delay: 1. send series of boot message pattern over UART 2. wait until kernel transmit all data 3. sleep small period of time At the same time, host needs to monitor input queue, data received on the UART and checking if it contains NAK byte by which BootROM informs that xmodem transfer is ready. But it is not possible to wait until kernel transmit all data on UART and at the same time in the one process to also wait for input data. This is limitation of POSIX tty API and also by linux kernel that it does not provide asynchronous function for waiting until all data are transmitted. There is only synchronous variant tcdrain(). So to correctly implement this handshake on systems with linux kernel, it is needed to use tcdrain() in separate thread. Implement sending of boot message pattern in one thread and reading of reply in the main thread. Use pthread library for threads. This change makes UART booting on Armada 385 more reliable. It is possible to start kwboot and power on board after minute and kwboot correctly put board into UART boot mode. Old implementation without separate thread has an issue that it read just one byte from UART input queue and then it send 128 message pattern to the output queue. If some noise was on UART then kwboot was not able to read BootROM response as its input queue was just overflowed and kwboot was sending more data than receiving. This change basically fixed above issue too. Signed-off-by: Pali Rohár --- tools/Makefile | 3 ++ tools/kwboot.c | 120 +++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 104 insertions(+), 19 deletions(-) diff --git a/tools/Makefile b/tools/Makefile index df941e0dca8d..c4a06dd9ba36 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -199,6 +199,9 @@ hostprogs-$(CONFIG_EXYNOS5250) += mkexynosspl hostprogs-$(CONFIG_EXYNOS5420) += mkexynosspl HOSTCFLAGS_mkexynosspl.o := -pedantic +HOSTCFLAGS_kwboot.o += -pthread +HOSTLDLIBS_kwboot += -pthread + ifdtool-objs := $(LIBFDT_OBJS) ifdtool.o hostprogs-$(CONFIG_X86) += ifdtool diff --git a/tools/kwboot.c b/tools/kwboot.c index 4e2acb52458a..9fd90b9bec71 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef __linux__ #include "termios_linux.h" @@ -717,37 +718,120 @@ out: return rc; } +static void * +kwboot_msg_write_handler(void *arg) +{ + int tty = *(int *)((void **)arg)[0]; + const void *msg = ((void **)arg)[1]; + int rsp_timeo = msg_rsp_timeo; + int i, dummy_oldtype; + + /* allow to cancel this thread at any time */ + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &dummy_oldtype); + + while (1) { + /* write 128 samples of message pattern into the output queue without waiting */ + for (i = 0; i < 128; i++) { + if (kwboot_tty_send(tty, msg, 8, 1) < 0) { + perror("\nFailed to send message pattern"); + exit(1); + } + } + /* wait until output queue is transmitted and then make pause */ + if (tcdrain(tty) < 0) { + perror("\nFailed to send message pattern"); + exit(1); + } + /* BootROM requires pause on UART after it detects message pattern */ + usleep(rsp_timeo * 1000); + } +} + +static int +kwboot_msg_start_thread(pthread_t *thread, int *tty, void *msg) +{ + void *arg[2]; + int rc; + + arg[0] = tty; + arg[1] = msg; + rc = pthread_create(thread, NULL, kwboot_msg_write_handler, arg); + if (rc) { + errno = rc; + return -1; + } + + return 0; +} + +static int +kwboot_msg_stop_thread(pthread_t thread) +{ + int rc; + + rc = pthread_cancel(thread); + if (rc) { + errno = rc; + return -1; + } + + rc = pthread_join(thread, NULL); + if (rc) { + errno = rc; + return -1; + } + + return 0; +} + static int kwboot_bootmsg(int tty) { struct kwboot_block block; - int rc; + pthread_t write_thread; + int rc, err; char c; - int count; - - kwboot_printv("Sending boot message. Please reboot the target..."); - do { - rc = tcflush(tty, TCIOFLUSH); - if (rc) - break; + /* flush input and output queue */ + tcflush(tty, TCIOFLUSH); - for (count = 0; count < 128; count++) { - rc = kwboot_tty_send(tty, kwboot_msg_boot, sizeof(kwboot_msg_boot), 0); - if (rc) - break; - } + rc = kwboot_msg_start_thread(&write_thread, &tty, kwboot_msg_boot); + if (rc) { + perror("Failed to start write thread"); + return rc; + } - rc = kwboot_tty_recv(tty, &c, 1, msg_rsp_timeo); + kwboot_printv("Sending boot message. Please reboot the target..."); + err = 0; + while (1) { kwboot_spinner(); - } while (rc || c != NAK); + rc = kwboot_tty_recv(tty, &c, 1, msg_rsp_timeo); + if (rc && errno == ETIMEDOUT) { + continue; + } else if (rc) { + err = errno; + break; + } + + if (c == NAK) + break; + } kwboot_printv("\n"); - if (rc) + rc = kwboot_msg_stop_thread(write_thread); + if (rc) { + perror("Failed to stop write thread"); return rc; + } + + if (err) { + errno = err; + perror("Failed to read response for boot message pattern"); + return -1; + } /* * At this stage we have sent more boot message patterns and BootROM @@ -1873,10 +1957,8 @@ main(int argc, char **argv) } } else if (bootmsg) { rc = kwboot_bootmsg(tty); - if (rc) { - perror("bootmsg"); + if (rc) goto out; - } } if (img) { -- 2.20.1