[U-Boot] [PATCH 0/3] console: Tidy up console_dev_is_serial()

With driver model this function does not work correctly and when CONFIG_DISPLAY_BOARDINFO_LATE is enabled we end up announcing U-Boot twice on the serial port. This causes the pytest framework to fail as it looks like a reset.
This series includes an interim patch to fix the test framework. However the correct fix is to avoid displaying the banner twice. This happens with driver model if the serial console device is not called "serial". Two patches enhance the check to use the uclass instead of the device name. This is a more reliable test.
We should not need to apply all three patches, but they are included in this series to allow the immediate test breakage to be fixed with a pytest change, while the other two patches are reviewed.
Simon Glass (3): test/py: Handle the banner being printed after relocation console: Unify the check for a serial console dm: console: Check for serial devices properly
common/console.c | 28 ++++++++++++++++++++++++++-- drivers/serial/serial-uclass.c | 2 +- include/stdio_dev.h | 1 + test/py/u_boot_console_base.py | 21 ++++++++++++++++++++- 4 files changed, 48 insertions(+), 4 deletions(-)

If CONFIG_DISPLAY_BOARDINFO_LATE is enabled, U-Boot displays the banner again after relocation so that it is visible on the video display. Detect this and allow it.
Note: This patch is only an interim fix. If it is applied we should consider reverting it later since it is not needed if U-Boot is working correctly.
Signed-off-by: Simon Glass sjg@chromium.org Fixes: b089538 (Allow displaying the U-Boot banner on a video display) ---
test/py/u_boot_console_base.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/test/py/u_boot_console_base.py b/test/py/u_boot_console_base.py index b1f474236e..3ea6b6a5d0 100644 --- a/test/py/u_boot_console_base.py +++ b/test/py/u_boot_console_base.py @@ -355,12 +355,31 @@ class ConsoleBase(object): self.u_boot_version_string = self.p.after while True: m = self.p.expect([self.prompt_compiled, - pattern_stop_autoboot_prompt] + self.bad_patterns) + pattern_stop_autoboot_prompt, pattern_u_boot_main_signon] + + self.bad_patterns) if m == 0: break if m == 1: self.p.send(' ') continue + + # If CONFIG_DISPLAY_BOARDINFO_LATE is defined then we will + # display the banner again after relocation. See + # console_announce_r() for the implementation. The original + # banner has two blank lines before it but this one has none. + # We can use this to distinguish a repeat of the banner from + # a reset of the board. Here we fail if we see even a single + # empty line in the characters leading up to the banner. + if m == 2: + before = self.p.before[-6:] + blank_lines = 0 + for ch in before: + if ch == '\n': + blank_lines += 1 + elif ch != '\r': + blank_lines = 0 + if blank_lines <= 1: + continue raise Exception('Bad pattern found on console: ' + self.bad_pattern_ids[m - 2]) self.at_prompt = True

On 07/27/2017 09:31 AM, Simon Glass wrote:
If CONFIG_DISPLAY_BOARDINFO_LATE is enabled, U-Boot displays the banner again after relocation so that it is visible on the video display. Detect this and allow it.
Note: This patch is only an interim fix. If it is applied we should consider reverting it later since it is not needed if U-Boot is working correctly.
It'd be useful if that paragraph could be expanded a bit; what exactly is the bug and how will it be fixed? The situation described in the first paragraph doesn't seem like a bug. Perhaps the fix be to delay the sign-on message until video output is available and only print it once, or not print the sign-on to serial when printing it a second time so that it's seen on video?
diff --git a/test/py/u_boot_console_base.py b/test/py/u_boot_console_base.py
@@ -355,12 +355,31 @@ class ConsoleBase(object): self.u_boot_version_string = self.p.after while True: m = self.p.expect([self.prompt_compiled,
pattern_stop_autoboot_prompt] + self.bad_patterns)
pattern_stop_autoboot_prompt, pattern_u_boot_main_signon] +
self.bad_patterns)
This doesn't seem quite right. At a very high level, the current code does this:
1) If SPL will print a sign-on: Wait for SPL to print sign-on 2) Wait for main U-Boot to print a sign-on 3) Wait for auto-boot prompt and interrupt it.
This change modifies (3) to alternatively wait for another sign-on prompt, which means it's doing 2 unrelated things. Better would be to just add a new standalone step to wait for the extra sign-on message:
1) If SPL will print a sign-on: Wait for SPL to print sign-on 2) Wait for main U-Boot to print a sign-on 3) If a duplicate sign-on message will be printed: Wait for duplicate sign-on from main U-Boot 4) Wait for auto-boot prompt and interrupt it.
Judging by the code quoted below, new step (3) above can use the value of bcfg.get('config_display_boardinfo_late', 'n') == 'y' to make the decision.
That has the advantage of not requiring the following heuristic to differentiate between expected sign-on messages and unexpected sign-on messages due to U-Boot crashing and restarting:
# If CONFIG_DISPLAY_BOARDINFO_LATE is defined then we will
# display the banner again after relocation. See
# console_announce_r() for the implementation. The original
# banner has two blank lines before it but this one has none.
# We can use this to distinguish a repeat of the banner from
# a reset of the board. Here we fail if we see even a single
# empty line in the characters leading up to the banner.

Hi Stephen,
On 27 July 2017 at 15:27, Stephen Warren swarren@wwwdotorg.org wrote:
On 07/27/2017 09:31 AM, Simon Glass wrote:
If CONFIG_DISPLAY_BOARDINFO_LATE is enabled, U-Boot displays the banner again after relocation so that it is visible on the video display. Detect this and allow it.
Note: This patch is only an interim fix. If it is applied we should consider reverting it later since it is not needed if U-Boot is working correctly.
It'd be useful if that paragraph could be expanded a bit; what exactly is the bug and how will it be fixed? The situation described in the first paragraph doesn't seem like a bug. Perhaps the fix be to delay the sign-on message until video output is available and only print it once, or not print the sign-on to serial when printing it a second time so that it's seen on video?
The bug is described /fixed in patches 2 & 3 of this series. I sent this patch in case there was urgency in fixing it.
diff --git a/test/py/u_boot_console_base.py b/test/py/u_boot_console_base.py
@@ -355,12 +355,31 @@ class ConsoleBase(object): self.u_boot_version_string = self.p.after while True: m = self.p.expect([self.prompt_compiled,
pattern_stop_autoboot_prompt] + self.bad_patterns)
pattern_stop_autoboot_prompt,
pattern_u_boot_main_signon] +
self.bad_patterns)
This doesn't seem quite right. At a very high level, the current code does this:
- If SPL will print a sign-on: Wait for SPL to print sign-on
- Wait for main U-Boot to print a sign-on
- Wait for auto-boot prompt and interrupt it.
This change modifies (3) to alternatively wait for another sign-on prompt,
Well actually the existing code already does this if you look closely. If it sees second sign-on it detects this and fails the test (presumably because it indicates there was an unexpected reboot). Otherwise I would not have bothered with this patch.
which means it's doing 2 unrelated things. Better would be to just add a new standalone step to wait for the extra sign-on message:
- If SPL will print a sign-on: Wait for SPL to print sign-on
- Wait for main U-Boot to print a sign-on
- If a duplicate sign-on message will be printed: Wait for duplicate sign-on from main U-Boot
- Wait for auto-boot prompt and interrupt it.
Judging by the code quoted below, new step (3) above can use the value of bcfg.get('config_display_boardinfo_late', 'n') == 'y' to make the decision.
That has the advantage of not requiring the following heuristic to differentiate between expected sign-on messages and unexpected sign-on messages due to U-Boot crashing and restarting:
Yes I think that would work. I did consider making it explicit on that option, which is indeed what causes the problem.
But if there are no objections I think it is best to skip this interim patch and apply the real fix (patches 2, 3) once they get some review.
# If CONFIG_DISPLAY_BOARDINFO_LATE is defined then we
will
# display the banner again after relocation. See
# console_announce_r() for the implementation. The
original
# banner has two blank lines before it but this one has
none.
# We can use this to distinguish a repeat of the banner
from
# a reset of the board. Here we fail if we see even a
single
# empty line in the characters leading up to the banner.
Regards, Simon

On 07/28/2017 09:57 PM, Simon Glass wrote:
Hi Stephen,
On 27 July 2017 at 15:27, Stephen Warren swarren@wwwdotorg.org wrote:
On 07/27/2017 09:31 AM, Simon Glass wrote:
If CONFIG_DISPLAY_BOARDINFO_LATE is enabled, U-Boot displays the banner again after relocation so that it is visible on the video display. Detect this and allow it.
Note: This patch is only an interim fix. If it is applied we should consider reverting it later since it is not needed if U-Boot is working correctly.
It'd be useful if that paragraph could be expanded a bit; what exactly is the bug and how will it be fixed? The situation described in the first paragraph doesn't seem like a bug. Perhaps the fix be to delay the sign-on message until video output is available and only print it once, or not print the sign-on to serial when printing it a second time so that it's seen on video?
The bug is described /fixed in patches 2 & 3 of this series. I sent this patch in case there was urgency in fixing it.
diff --git a/test/py/u_boot_console_base.py b/test/py/u_boot_console_base.py
@@ -355,12 +355,31 @@ class ConsoleBase(object): self.u_boot_version_string = self.p.after while True: m = self.p.expect([self.prompt_compiled,
pattern_stop_autoboot_prompt] + self.bad_patterns)
pattern_stop_autoboot_prompt,
pattern_u_boot_main_signon] +
self.bad_patterns)
This doesn't seem quite right. At a very high level, the current code does this:
- If SPL will print a sign-on: Wait for SPL to print sign-on
- Wait for main U-Boot to print a sign-on
- Wait for auto-boot prompt and interrupt it.
This change modifies (3) to alternatively wait for another sign-on prompt,
Well actually the existing code already does this if you look closely. If it sees second sign-on it detects this and fails the test (presumably because it indicates there was an unexpected reboot). Otherwise I would not have bothered with this patch.
But it's doing it in a much more "after-the-fact" and brittle way.
which means it's doing 2 unrelated things. Better would be to just add a new standalone step to wait for the extra sign-on message:
- If SPL will print a sign-on: Wait for SPL to print sign-on
- Wait for main U-Boot to print a sign-on
- If a duplicate sign-on message will be printed: Wait for duplicate sign-on from main U-Boot
- Wait for auto-boot prompt and interrupt it.
Judging by the code quoted below, new step (3) above can use the value of bcfg.get('config_display_boardinfo_late', 'n') == 'y' to make the decision.
That has the advantage of not requiring the following heuristic to differentiate between expected sign-on messages and unexpected sign-on messages due to U-Boot crashing and restarting:
Yes I think that would work. I did consider making it explicit on that option, which is indeed what causes the problem.
But if there are no objections I think it is best to skip this interim patch and apply the real fix (patches 2, 3) once they get some review.
Yes, if patches 2/3 fix the root-cause, then I'd agree let's just apply those instead.

Put the check for whether a console is a serial device in a function so that we can share the code in the two places that use it.
Signed-off-by: Simon Glass sjg@chromium.org ---
common/console.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/common/console.c b/common/console.c index c6156f33bb..80401acf5b 100644 --- a/common/console.c +++ b/common/console.c @@ -146,6 +146,21 @@ static int console_setfile(int file, struct stdio_dev * dev) return error; }
+/** + * console_dev_is_serial() - Check if a stdio device is a serial device + * + * @sdev: Device to check + * @return true if this device is a serial device + */ +static bool console_dev_is_serial(struct stdio_dev *sdev) +{ + bool is_serial; + + is_serial = !strcmp(sdev->name, "serial"); + + return is_serial; +} + #if CONFIG_IS_ENABLED(CONSOLE_MUX) /** Console I/O multiplexing *******************************************/
@@ -210,7 +225,7 @@ static void console_puts_noserial(int file, const char *s)
for (i = 0; i < cd_count[file]; i++) { dev = console_devices[file][i]; - if (dev->puts != NULL && strcmp(dev->name, "serial") != 0) + if (dev->puts != NULL && !console_dev_is_serial(dev)) dev->puts(dev, s); } } @@ -249,7 +264,7 @@ static inline void console_putc(int file, const char c)
static inline void console_puts_noserial(int file, const char *s) { - if (strcmp(stdio_devices[file]->name, "serial") != 0) + if (!console_dev_is_serial(stdio_devices[file])) stdio_devices[file]->puts(stdio_devices[file], s); }

On Thu, Jul 27, 2017 at 09:31:03AM -0600, Simon Glass wrote:
Put the check for whether a console is a serial device in a function so that we can share the code in the two places that use it.
Signed-off-by: Simon Glass sjg@chromium.org
Applied to u-boot/master, thanks!

With driver model the serial device is often not called "serial". Mark driver-model stdio devices so that they can be detected and we can look up the uclass. This is a more reliable way of finding out whether the console is connected to a serial device or not.
Signed-off-by: Simon Glass sjg@chromium.org ---
common/console.c | 11 ++++++++++- drivers/serial/serial-uclass.c | 2 +- include/stdio_dev.h | 1 + 3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/common/console.c b/common/console.c index 80401acf5b..e9164d7c9d 100644 --- a/common/console.c +++ b/common/console.c @@ -8,6 +8,7 @@ #include <common.h> #include <console.h> #include <debug_uart.h> +#include <dm.h> #include <stdarg.h> #include <iomux.h> #include <malloc.h> @@ -150,12 +151,20 @@ static int console_setfile(int file, struct stdio_dev * dev) * console_dev_is_serial() - Check if a stdio device is a serial device * * @sdev: Device to check - * @return true if this device is a serial device + * @return true if this device is in the serial uclass (or for pre-driver-model, + * whether it is called "serial". */ static bool console_dev_is_serial(struct stdio_dev *sdev) { bool is_serial;
+#ifdef CONFIG_DM_SERIAL + if (sdev->flags & DEV_FLAGS_DM) { + struct udevice *dev = sdev->priv; + + is_serial = device_get_uclass_id(dev) == UCLASS_SERIAL; + } else +#endif is_serial = !strcmp(sdev->name, "serial");
return is_serial; diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index f360534683..db51863598 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -353,7 +353,7 @@ static int serial_post_probe(struct udevice *dev) memset(&sdev, '\0', sizeof(sdev));
strncpy(sdev.name, dev->name, sizeof(sdev.name)); - sdev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; + sdev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_DM; sdev.priv = dev; sdev.putc = serial_stub_putc; sdev.puts = serial_stub_puts; diff --git a/include/stdio_dev.h b/include/stdio_dev.h index e4fc8b138b..3164fa2a55 100644 --- a/include/stdio_dev.h +++ b/include/stdio_dev.h @@ -16,6 +16,7 @@
#define DEV_FLAGS_INPUT 0x00000001 /* Device can be used as input console */ #define DEV_FLAGS_OUTPUT 0x00000002 /* Device can be used as output console */ +#define DEV_FLAGS_DM 0x00000004 /* Device priv is a struct udevice * */
/* Device information */ struct stdio_dev {

On Thu, Jul 27, 2017 at 09:31:04AM -0600, Simon Glass wrote:
With driver model the serial device is often not called "serial". Mark driver-model stdio devices so that they can be detected and we can look up the uclass. This is a more reliable way of finding out whether the console is connected to a serial device or not.
Signed-off-by: Simon Glass sjg@chromium.org
Applied to u-boot/master, thanks!
participants (3)
-
Simon Glass
-
Stephen Warren
-
Tom Rini