diff mbox series

[v2,2/6] console: Implement flush() function

Message ID 20220811123925.23981-3-pali@kernel.org
State Superseded
Delegated to: Tom Rini
Headers show
Series console: Implement flush() function | expand

Commit Message

Pali Rohár Aug. 11, 2022, 12:39 p.m. UTC
On certain places it is required to flush output print buffers to ensure
that text strings were sent to console or serial devices. For example when
printing message that U-Boot is going to boot kernel or when U-Boot is
going to change baudrate of terminal device.

Therefore introduce a new flush() and fflush() functions into console code.
These functions will call .flush callback of associated stdio_dev device.

As this function may increase U-Boot side, allow to compile U-Boot without
this function. For this purpose there is a new config CONSOLE_FLUSH_SUPPORT
which is enabled by default and can be disabled. It is a good idea to have
this option enabled for all boards which have enough space for it.

When option is disabled when U-Boot defines just empty static inline
function fflush() to avoid ifdefs in other code.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 common/Kconfig      |  6 +++++
 common/console.c    | 63 +++++++++++++++++++++++++++++++++++++++++++++
 include/_exports.h  |  3 +++
 include/stdio.h     | 15 +++++++++++
 include/stdio_dev.h |  4 +++
 5 files changed, 91 insertions(+)

Comments

Simon Glass Aug. 11, 2022, 2:47 p.m. UTC | #1
Hi Pali,

On Thu, 11 Aug 2022 at 06:39, Pali Rohár <pali@kernel.org> wrote:
>
> On certain places it is required to flush output print buffers to ensure
> that text strings were sent to console or serial devices. For example when
> printing message that U-Boot is going to boot kernel or when U-Boot is
> going to change baudrate of terminal device.
>
> Therefore introduce a new flush() and fflush() functions into console code.
> These functions will call .flush callback of associated stdio_dev device.
>
> As this function may increase U-Boot side, allow to compile U-Boot without
> this function. For this purpose there is a new config CONSOLE_FLUSH_SUPPORT
> which is enabled by default and can be disabled. It is a good idea to have
> this option enabled for all boards which have enough space for it.
>
> When option is disabled when U-Boot defines just empty static inline
> function fflush() to avoid ifdefs in other code.
>
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  common/Kconfig      |  6 +++++
>  common/console.c    | 63 +++++++++++++++++++++++++++++++++++++++++++++
>  include/_exports.h  |  3 +++
>  include/stdio.h     | 15 +++++++++++
>  include/stdio_dev.h |  4 +++
>  5 files changed, 91 insertions(+)
>
> diff --git a/common/Kconfig b/common/Kconfig
> index e7914ca750a3..109741cc6c44 100644
> --- a/common/Kconfig
> +++ b/common/Kconfig
> @@ -186,6 +186,12 @@ config PRE_CON_BUF_ADDR
>           We should consider removing this option and allocating the memory
>           in board_init_f_init_reserve() instead.
>
> +config CONSOLE_FLUSH_SUPPORT
> +       bool "Enable console flush support"
> +       default y
> +       help
> +         This enables compilation of flush() function for console flush support.

This needs at least two more lines, I think. Perhaps you can explain
what flush does and the fact that there is no timeout?

> +
>  config CONSOLE_MUX
>         bool "Enable console multiplexing"
>         default y if DM_VIDEO || VIDEO || LCD
> diff --git a/common/console.c b/common/console.c
> index dc071f1ed665..42415e34d16f 100644
> --- a/common/console.c
> +++ b/common/console.c
> @@ -198,6 +198,9 @@ static int console_setfile(int file, struct stdio_dev * dev)
>                 case stdout:
>                         gd->jt->putc  = putc;
>                         gd->jt->puts  = puts;
> +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT

How about CONFIG_IS_ENABLED() so we don't enable this in SPL too?

> +                       gd->jt->flush = flush;
> +#endif
>                         gd->jt->printf = printf;
>                         break;
>                 }
> @@ -363,6 +366,19 @@ static void console_puts(int file, const char *s)
>         }
>  }
>
> +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
> +static void console_flush(int file)
> +{
> +       int i;
> +       struct stdio_dev *dev;
> +
> +       for_each_console_dev(i, file, dev) {
> +               if (dev->flush != NULL)
> +                       dev->flush(dev);
> +       }
> +}
> +#endif
> +
>  #if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
>  static inline void console_doenv(int file, struct stdio_dev *dev)
>  {
> @@ -412,6 +428,14 @@ static inline void console_puts(int file, const char *s)
>         stdio_devices[file]->puts(stdio_devices[file], s);
>  }
>
> +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT

I hope you can drop this #ifdef - see below.

> +static inline void console_flush(int file)
> +{
> +       if (stdio_devices[file]->flush)
> +               stdio_devices[file]->flush(stdio_devices[file]);
> +}
> +#endif
> +
>  #if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
>  static inline void console_doenv(int file, struct stdio_dev *dev)
>  {
> @@ -525,6 +549,14 @@ void fputs(int file, const char *s)
>                 console_puts(file, s);
>  }
>
> +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
> +void fflush(int file)
> +{
> +       if (file < MAX_FILES)
> +               console_flush(file);
> +}
> +#endif
> +
>  int fprintf(int file, const char *fmt, ...)
>  {
>         va_list args;
> @@ -731,6 +763,37 @@ void puts(const char *s)
>         }
>  }
>
> +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
> +void flush(void)
> +{
> +       if (!gd)
> +               return;
> +
> +       /* sandbox can send characters to stdout before it has a console */
> +       if (IS_ENABLED(CONFIG_SANDBOX) && !(gd->flags & GD_FLG_SERIAL_READY)) {
> +               os_flush();
> +               return;
> +       }
> +
> +       if (IS_ENABLED(CONFIG_DEBUG_UART) && !(gd->flags & GD_FLG_SERIAL_READY))
> +               return;
> +
> +       if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT))
> +               return;
> +
> +       if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
> +               return;
> +
> +       if (!gd->have_console)
> +               return;
> +
> +       if (gd->flags & GD_FLG_DEVINIT) {
> +               /* Send to the standard output */
> +               fflush(stdout);
> +       }
> +}
> +#endif
> +
>  #ifdef CONFIG_CONSOLE_RECORD
>  int console_record_init(void)
>  {
> diff --git a/include/_exports.h b/include/_exports.h
> index f6df8b610734..1af946fac327 100644
> --- a/include/_exports.h
> +++ b/include/_exports.h
> @@ -12,6 +12,9 @@
>         EXPORT_FUNC(tstc, int, tstc, void)
>         EXPORT_FUNC(putc, void, putc, const char)
>         EXPORT_FUNC(puts, void, puts, const char *)
> +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
> +       EXPORT_FUNC(flush, void, flush, void)
> +#endif
>         EXPORT_FUNC(printf, int, printf, const char*, ...)
>  #if (defined(CONFIG_X86) && !defined(CONFIG_X86_64)) || defined(CONFIG_PPC)
>         EXPORT_FUNC(irq_install_handler, void, install_hdlr,
> diff --git a/include/stdio.h b/include/stdio.h
> index 1939a48f0fb6..3241e2d493fa 100644
> --- a/include/stdio.h
> +++ b/include/stdio.h
> @@ -15,6 +15,11 @@ int tstc(void);
>                 defined(CONFIG_SPL_SERIAL))
>  void putc(const char c);
>  void puts(const char *s);
> +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
> +void flush(void);
> +#else
> +static inline void flush(void) {}
> +#endif
>  int __printf(1, 2) printf(const char *fmt, ...);
>  int vprintf(const char *fmt, va_list args);
>  #else
> @@ -26,6 +31,10 @@ static inline void puts(const char *s)
>  {
>  }
>
> +static inline void flush(void)
> +{
> +}
> +
>  static inline int __printf(1, 2) printf(const char *fmt, ...)
>  {
>         return 0;
> @@ -48,11 +57,17 @@ static inline int vprintf(const char *fmt, va_list args)
>  /* stderr */
>  #define eputc(c)               fputc(stderr, c)
>  #define eputs(s)               fputs(stderr, s)
> +#define eflush()               fflush(stderr)
>  #define eprintf(fmt, args...)  fprintf(stderr, fmt, ##args)
>
>  int __printf(2, 3) fprintf(int file, const char *fmt, ...);
>  void fputs(int file, const char *s);
>  void fputc(int file, const char c);
> +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
> +void fflush(int file);
> +#else
> +static inline void fflush(int file) {}
> +#endif
>  int ftstc(int file);
>  int fgetc(int file);
>
> diff --git a/include/stdio_dev.h b/include/stdio_dev.h
> index 270fa2729fb2..06278366ae88 100644
> --- a/include/stdio_dev.h
> +++ b/include/stdio_dev.h
> @@ -37,6 +37,10 @@ struct stdio_dev {
>         void (*putc)(struct stdio_dev *dev, const char c);
>         /* To put a string (accelerator) */
>         void (*puts)(struct stdio_dev *dev, const char *s);
> +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT

I'd argue it isn't worth the #ifdef and we might as well have this
member here always. Then you can drop some #ifdefs from your code.

> +       /* To flush output queue */
> +       void (*flush)(struct stdio_dev *dev);
> +#endif
>
>  /* INPUT functions */
>
> --
> 2.20.1
>

Regards,
SImon
Pali Rohár Aug. 11, 2022, 2:49 p.m. UTC | #2
On Thursday 11 August 2022 08:47:50 Simon Glass wrote:
> > diff --git a/include/stdio_dev.h b/include/stdio_dev.h
> > index 270fa2729fb2..06278366ae88 100644
> > --- a/include/stdio_dev.h
> > +++ b/include/stdio_dev.h
> > @@ -37,6 +37,10 @@ struct stdio_dev {
> >         void (*putc)(struct stdio_dev *dev, const char c);
> >         /* To put a string (accelerator) */
> >         void (*puts)(struct stdio_dev *dev, const char *s);
> > +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
> 
> I'd argue it isn't worth the #ifdef and we might as well have this
> member here always. Then you can drop some #ifdefs from your code.

But then it will increase binary code size.

> > +       /* To flush output queue */
> > +       void (*flush)(struct stdio_dev *dev);
> > +#endif
> >
> >  /* INPUT functions */
> >
> > --
> > 2.20.1
> >
> 
> Regards,
> SImon
Simon Glass Aug. 12, 2022, 12:08 a.m. UTC | #3
Hi Pali,

On Thu, 11 Aug 2022 at 08:50, Pali Rohár <pali@kernel.org> wrote:
>
> On Thursday 11 August 2022 08:47:50 Simon Glass wrote:
> > > diff --git a/include/stdio_dev.h b/include/stdio_dev.h
> > > index 270fa2729fb2..06278366ae88 100644
> > > --- a/include/stdio_dev.h
> > > +++ b/include/stdio_dev.h
> > > @@ -37,6 +37,10 @@ struct stdio_dev {
> > >         void (*putc)(struct stdio_dev *dev, const char c);
> > >         /* To put a string (accelerator) */
> > >         void (*puts)(struct stdio_dev *dev, const char *s);
> > > +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
> >
> > I'd argue it isn't worth the #ifdef and we might as well have this
> > member here always. Then you can drop some #ifdefs from your code.
>
> But then it will increase binary code size.

Using the member will increase code size. But I think the only place
you need an #ifdef for that is when you include it in the driver
struct. You can use __maybe_unused in the other place.

Having the member will only increase memory usage, not code size.

Regards,
Simon
Pali Rohár Aug. 12, 2022, 9:01 a.m. UTC | #4
On Thursday 11 August 2022 18:08:46 Simon Glass wrote:
> Hi Pali,
> 
> On Thu, 11 Aug 2022 at 08:50, Pali Rohár <pali@kernel.org> wrote:
> >
> > On Thursday 11 August 2022 08:47:50 Simon Glass wrote:
> > > > diff --git a/include/stdio_dev.h b/include/stdio_dev.h
> > > > index 270fa2729fb2..06278366ae88 100644
> > > > --- a/include/stdio_dev.h
> > > > +++ b/include/stdio_dev.h
> > > > @@ -37,6 +37,10 @@ struct stdio_dev {
> > > >         void (*putc)(struct stdio_dev *dev, const char c);
> > > >         /* To put a string (accelerator) */
> > > >         void (*puts)(struct stdio_dev *dev, const char *s);
> > > > +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
> > >
> > > I'd argue it isn't worth the #ifdef and we might as well have this
> > > member here always. Then you can drop some #ifdefs from your code.
> >
> > But then it will increase binary code size.
> 
> Using the member will increase code size. But I think the only place
> you need an #ifdef for that is when you include it in the driver
> struct. You can use __maybe_unused in the other place.
> 
> Having the member will only increase memory usage, not code size.

But static memory structures are part of the u-boot.bin binary and also
their usage increase code size (required copy, etc...), so at the end it
increase code size.

> Regards,
> Simon
Simon Glass Aug. 12, 2022, 3:11 p.m. UTC | #5
Hi Pali,

On Fri, 12 Aug 2022 at 03:01, Pali Rohár <pali@kernel.org> wrote:
>
> On Thursday 11 August 2022 18:08:46 Simon Glass wrote:
> > Hi Pali,
> >
> > On Thu, 11 Aug 2022 at 08:50, Pali Rohár <pali@kernel.org> wrote:
> > >
> > > On Thursday 11 August 2022 08:47:50 Simon Glass wrote:
> > > > > diff --git a/include/stdio_dev.h b/include/stdio_dev.h
> > > > > index 270fa2729fb2..06278366ae88 100644
> > > > > --- a/include/stdio_dev.h
> > > > > +++ b/include/stdio_dev.h
> > > > > @@ -37,6 +37,10 @@ struct stdio_dev {
> > > > >         void (*putc)(struct stdio_dev *dev, const char c);
> > > > >         /* To put a string (accelerator) */
> > > > >         void (*puts)(struct stdio_dev *dev, const char *s);
> > > > > +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
> > > >
> > > > I'd argue it isn't worth the #ifdef and we might as well have this
> > > > member here always. Then you can drop some #ifdefs from your code.
> > >
> > > But then it will increase binary code size.
> >
> > Using the member will increase code size. But I think the only place
> > you need an #ifdef for that is when you include it in the driver
> > struct. You can use __maybe_unused in the other place.
> >
> > Having the member will only increase memory usage, not code size.
>
> But static memory structures are part of the u-boot.bin binary and also
> their usage increase code size (required copy, etc...), so at the end it
> increase code size.

From what I understand stdio_dev is allocated at runtime in BSS:

struct stdio_dev *stdio_devices[] = { NULL, NULL, NULL };

(the NULL stuff should not be there, but does nothing, I believe)

So long as no code accesses your new member, then it should only
affect the BSS size.

If you are very worried about it, you could use the technique in
asm-generic/global_data.h to avoid #ifdefs in the C code:

#ifdef CONFIG_GENERATE_ACPI_TABLE
#define gd_acpi_start() gd->acpi_start
#define gd_set_acpi_start(addr) gd->acpi_start = addr
#else
#define gd_acpi_start() 0UL
#define gd_set_acpi_start(addr)
#endif

Regards,
Simon
Pali Rohár Aug. 12, 2022, 3:17 p.m. UTC | #6
On Friday 12 August 2022 09:11:10 Simon Glass wrote:
> Hi Pali,
> 
> On Fri, 12 Aug 2022 at 03:01, Pali Rohár <pali@kernel.org> wrote:
> >
> > On Thursday 11 August 2022 18:08:46 Simon Glass wrote:
> > > Hi Pali,
> > >
> > > On Thu, 11 Aug 2022 at 08:50, Pali Rohár <pali@kernel.org> wrote:
> > > >
> > > > On Thursday 11 August 2022 08:47:50 Simon Glass wrote:
> > > > > > diff --git a/include/stdio_dev.h b/include/stdio_dev.h
> > > > > > index 270fa2729fb2..06278366ae88 100644
> > > > > > --- a/include/stdio_dev.h
> > > > > > +++ b/include/stdio_dev.h
> > > > > > @@ -37,6 +37,10 @@ struct stdio_dev {
> > > > > >         void (*putc)(struct stdio_dev *dev, const char c);
> > > > > >         /* To put a string (accelerator) */
> > > > > >         void (*puts)(struct stdio_dev *dev, const char *s);
> > > > > > +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
> > > > >
> > > > > I'd argue it isn't worth the #ifdef and we might as well have this
> > > > > member here always. Then you can drop some #ifdefs from your code.
> > > >
> > > > But then it will increase binary code size.
> > >
> > > Using the member will increase code size. But I think the only place
> > > you need an #ifdef for that is when you include it in the driver
> > > struct. You can use __maybe_unused in the other place.
> > >
> > > Having the member will only increase memory usage, not code size.
> >
> > But static memory structures are part of the u-boot.bin binary and also
> > their usage increase code size (required copy, etc...), so at the end it
> > increase code size.
> 
> From what I understand stdio_dev is allocated at runtime in BSS:
> 
> struct stdio_dev *stdio_devices[] = { NULL, NULL, NULL };
> 
> (the NULL stuff should not be there, but does nothing, I believe)
> 
> So long as no code accesses your new member, then it should only
> affect the BSS size.

Code of course has to access new member. How otherwise would be able to
call that new callbacks? E.g. all new code in patch 2/6 or 3/6.

> If you are very worried about it, you could use the technique in
> asm-generic/global_data.h to avoid #ifdefs in the C code:
> 
> #ifdef CONFIG_GENERATE_ACPI_TABLE
> #define gd_acpi_start() gd->acpi_start
> #define gd_set_acpi_start(addr) gd->acpi_start = addr
> #else
> #define gd_acpi_start() 0UL
> #define gd_set_acpi_start(addr)
> #endif
> 
> Regards,
> Simon
Simon Glass Aug. 13, 2022, 2:21 a.m. UTC | #7
Hi Pali,

On Fri, 12 Aug 2022 at 09:17, Pali Rohár <pali@kernel.org> wrote:
>
> On Friday 12 August 2022 09:11:10 Simon Glass wrote:
> > Hi Pali,
> >
> > On Fri, 12 Aug 2022 at 03:01, Pali Rohár <pali@kernel.org> wrote:
> > >
> > > On Thursday 11 August 2022 18:08:46 Simon Glass wrote:
> > > > Hi Pali,
> > > >
> > > > On Thu, 11 Aug 2022 at 08:50, Pali Rohár <pali@kernel.org> wrote:
> > > > >
> > > > > On Thursday 11 August 2022 08:47:50 Simon Glass wrote:
> > > > > > > diff --git a/include/stdio_dev.h b/include/stdio_dev.h
> > > > > > > index 270fa2729fb2..06278366ae88 100644
> > > > > > > --- a/include/stdio_dev.h
> > > > > > > +++ b/include/stdio_dev.h
> > > > > > > @@ -37,6 +37,10 @@ struct stdio_dev {
> > > > > > >         void (*putc)(struct stdio_dev *dev, const char c);
> > > > > > >         /* To put a string (accelerator) */
> > > > > > >         void (*puts)(struct stdio_dev *dev, const char *s);
> > > > > > > +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
> > > > > >
> > > > > > I'd argue it isn't worth the #ifdef and we might as well have this
> > > > > > member here always. Then you can drop some #ifdefs from your code.
> > > > >
> > > > > But then it will increase binary code size.
> > > >
> > > > Using the member will increase code size. But I think the only place
> > > > you need an #ifdef for that is when you include it in the driver
> > > > struct. You can use __maybe_unused in the other place.
> > > >
> > > > Having the member will only increase memory usage, not code size.
> > >
> > > But static memory structures are part of the u-boot.bin binary and also
> > > their usage increase code size (required copy, etc...), so at the end it
> > > increase code size.
> >
> > From what I understand stdio_dev is allocated at runtime in BSS:
> >
> > struct stdio_dev *stdio_devices[] = { NULL, NULL, NULL };
> >
> > (the NULL stuff should not be there, but does nothing, I believe)
> >
> > So long as no code accesses your new member, then it should only
> > affect the BSS size.
>
> Code of course has to access new member. How otherwise would be able to
> call that new callbacks? E.g. all new code in patch 2/6 or 3/6.

Yes, see below. Also, do check whether it actually adds code or not.

>
> > If you are very worried about it, you could use the technique in
> > asm-generic/global_data.h to avoid #ifdefs in the C code:
> >
> > #ifdef CONFIG_GENERATE_ACPI_TABLE
> > #define gd_acpi_start() gd->acpi_start
> > #define gd_set_acpi_start(addr) gd->acpi_start = addr
> > #else
> > #define gd_acpi_start() 0UL
> > #define gd_set_acpi_start(addr)
> > #endif
> >
> > Regards,
> > Simon

Regards,
Simon
Pali Rohár Aug. 25, 2022, 2:20 p.m. UTC | #8
On Friday 12 August 2022 20:21:00 Simon Glass wrote:
> Hi Pali,
> 
> On Fri, 12 Aug 2022 at 09:17, Pali Rohár <pali@kernel.org> wrote:
> >
> > On Friday 12 August 2022 09:11:10 Simon Glass wrote:
> > > Hi Pali,
> > >
> > > On Fri, 12 Aug 2022 at 03:01, Pali Rohár <pali@kernel.org> wrote:
> > > >
> > > > On Thursday 11 August 2022 18:08:46 Simon Glass wrote:
> > > > > Hi Pali,
> > > > >
> > > > > On Thu, 11 Aug 2022 at 08:50, Pali Rohár <pali@kernel.org> wrote:
> > > > > >
> > > > > > On Thursday 11 August 2022 08:47:50 Simon Glass wrote:
> > > > > > > > diff --git a/include/stdio_dev.h b/include/stdio_dev.h
> > > > > > > > index 270fa2729fb2..06278366ae88 100644
> > > > > > > > --- a/include/stdio_dev.h
> > > > > > > > +++ b/include/stdio_dev.h
> > > > > > > > @@ -37,6 +37,10 @@ struct stdio_dev {
> > > > > > > >         void (*putc)(struct stdio_dev *dev, const char c);
> > > > > > > >         /* To put a string (accelerator) */
> > > > > > > >         void (*puts)(struct stdio_dev *dev, const char *s);
> > > > > > > > +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
> > > > > > >
> > > > > > > I'd argue it isn't worth the #ifdef and we might as well have this
> > > > > > > member here always. Then you can drop some #ifdefs from your code.
> > > > > >
> > > > > > But then it will increase binary code size.
> > > > >
> > > > > Using the member will increase code size. But I think the only place
> > > > > you need an #ifdef for that is when you include it in the driver
> > > > > struct. You can use __maybe_unused in the other place.
> > > > >
> > > > > Having the member will only increase memory usage, not code size.
> > > >
> > > > But static memory structures are part of the u-boot.bin binary and also
> > > > their usage increase code size (required copy, etc...), so at the end it
> > > > increase code size.
> > >
> > > From what I understand stdio_dev is allocated at runtime in BSS:
> > >
> > > struct stdio_dev *stdio_devices[] = { NULL, NULL, NULL };
> > >
> > > (the NULL stuff should not be there, but does nothing, I believe)
> > >
> > > So long as no code accesses your new member, then it should only
> > > affect the BSS size.
> >
> > Code of course has to access new member. How otherwise would be able to
> > call that new callbacks? E.g. all new code in patch 2/6 or 3/6.
> 
> Yes, see below. Also, do check whether it actually adds code or not.
> 
> >
> > > If you are very worried about it, you could use the technique in
> > > asm-generic/global_data.h to avoid #ifdefs in the C code:
> > >
> > > #ifdef CONFIG_GENERATE_ACPI_TABLE
> > > #define gd_acpi_start() gd->acpi_start
> > > #define gd_set_acpi_start(addr) gd->acpi_start = addr
> > > #else
> > > #define gd_acpi_start() 0UL
> > > #define gd_set_acpi_start(addr)
> > > #endif
> > >
> > > Regards,
> > > Simon
> 
> Regards,
> Simon

But in this case, it is needed to introduce a new special macro and hide
assigning code into it. In my opinion such macro with side effect and
worse than writing it explicitly - open coded to show what the code is
doing.
Simon Glass Aug. 25, 2022, 3:08 p.m. UTC | #9
Hi Pali,

On Thu, 25 Aug 2022 at 08:20, Pali Rohár <pali@kernel.org> wrote:
>
> On Friday 12 August 2022 20:21:00 Simon Glass wrote:
> > Hi Pali,
> >
> > On Fri, 12 Aug 2022 at 09:17, Pali Rohár <pali@kernel.org> wrote:
> > >
> > > On Friday 12 August 2022 09:11:10 Simon Glass wrote:
> > > > Hi Pali,
> > > >
> > > > On Fri, 12 Aug 2022 at 03:01, Pali Rohár <pali@kernel.org> wrote:
> > > > >
> > > > > On Thursday 11 August 2022 18:08:46 Simon Glass wrote:
> > > > > > Hi Pali,
> > > > > >
> > > > > > On Thu, 11 Aug 2022 at 08:50, Pali Rohár <pali@kernel.org> wrote:
> > > > > > >
> > > > > > > On Thursday 11 August 2022 08:47:50 Simon Glass wrote:
> > > > > > > > > diff --git a/include/stdio_dev.h b/include/stdio_dev.h
> > > > > > > > > index 270fa2729fb2..06278366ae88 100644
> > > > > > > > > --- a/include/stdio_dev.h
> > > > > > > > > +++ b/include/stdio_dev.h
> > > > > > > > > @@ -37,6 +37,10 @@ struct stdio_dev {
> > > > > > > > >         void (*putc)(struct stdio_dev *dev, const char c);
> > > > > > > > >         /* To put a string (accelerator) */
> > > > > > > > >         void (*puts)(struct stdio_dev *dev, const char *s);
> > > > > > > > > +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
> > > > > > > >
> > > > > > > > I'd argue it isn't worth the #ifdef and we might as well have this
> > > > > > > > member here always. Then you can drop some #ifdefs from your code.
> > > > > > >
> > > > > > > But then it will increase binary code size.
> > > > > >
> > > > > > Using the member will increase code size. But I think the only place
> > > > > > you need an #ifdef for that is when you include it in the driver
> > > > > > struct. You can use __maybe_unused in the other place.
> > > > > >
> > > > > > Having the member will only increase memory usage, not code size.
> > > > >
> > > > > But static memory structures are part of the u-boot.bin binary and also
> > > > > their usage increase code size (required copy, etc...), so at the end it
> > > > > increase code size.
> > > >
> > > > From what I understand stdio_dev is allocated at runtime in BSS:
> > > >
> > > > struct stdio_dev *stdio_devices[] = { NULL, NULL, NULL };
> > > >
> > > > (the NULL stuff should not be there, but does nothing, I believe)
> > > >
> > > > So long as no code accesses your new member, then it should only
> > > > affect the BSS size.
> > >
> > > Code of course has to access new member. How otherwise would be able to
> > > call that new callbacks? E.g. all new code in patch 2/6 or 3/6.
> >
> > Yes, see below. Also, do check whether it actually adds code or not.
> >
> > >
> > > > If you are very worried about it, you could use the technique in
> > > > asm-generic/global_data.h to avoid #ifdefs in the C code:
> > > >
> > > > #ifdef CONFIG_GENERATE_ACPI_TABLE
> > > > #define gd_acpi_start() gd->acpi_start
> > > > #define gd_set_acpi_start(addr) gd->acpi_start = addr
> > > > #else
> > > > #define gd_acpi_start() 0UL
> > > > #define gd_set_acpi_start(addr)
> > > > #endif
> > > >
> > > > Regards,
> > > > Simon
> >
> > Regards,
> > Simon
>
> But in this case, it is needed to introduce a new special macro and hide
> assigning code into it. In my opinion such macro with side effect and
> worse than writing it explicitly - open coded to show what the code is
> doing.

You can use an inline function if you prefer.

My main objection is to adding #ifdefs to C files. They are OK (for
now) in driver struct declarations, where some members are optional.
But I think it is worth going to some lengths to avoid them elsewhere.

+Tom Rini for thoughts on this

Regards,
SImon
Pali Rohár Aug. 31, 2022, 9:13 a.m. UTC | #10
On Thursday 25 August 2022 09:08:18 Simon Glass wrote:
> Hi Pali,
> 
> On Thu, 25 Aug 2022 at 08:20, Pali Rohár <pali@kernel.org> wrote:
> >
> > On Friday 12 August 2022 20:21:00 Simon Glass wrote:
> > > Hi Pali,
> > >
> > > On Fri, 12 Aug 2022 at 09:17, Pali Rohár <pali@kernel.org> wrote:
> > > >
> > > > On Friday 12 August 2022 09:11:10 Simon Glass wrote:
> > > > > Hi Pali,
> > > > >
> > > > > On Fri, 12 Aug 2022 at 03:01, Pali Rohár <pali@kernel.org> wrote:
> > > > > >
> > > > > > On Thursday 11 August 2022 18:08:46 Simon Glass wrote:
> > > > > > > Hi Pali,
> > > > > > >
> > > > > > > On Thu, 11 Aug 2022 at 08:50, Pali Rohár <pali@kernel.org> wrote:
> > > > > > > >
> > > > > > > > On Thursday 11 August 2022 08:47:50 Simon Glass wrote:
> > > > > > > > > > diff --git a/include/stdio_dev.h b/include/stdio_dev.h
> > > > > > > > > > index 270fa2729fb2..06278366ae88 100644
> > > > > > > > > > --- a/include/stdio_dev.h
> > > > > > > > > > +++ b/include/stdio_dev.h
> > > > > > > > > > @@ -37,6 +37,10 @@ struct stdio_dev {
> > > > > > > > > >         void (*putc)(struct stdio_dev *dev, const char c);
> > > > > > > > > >         /* To put a string (accelerator) */
> > > > > > > > > >         void (*puts)(struct stdio_dev *dev, const char *s);
> > > > > > > > > > +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
> > > > > > > > >
> > > > > > > > > I'd argue it isn't worth the #ifdef and we might as well have this
> > > > > > > > > member here always. Then you can drop some #ifdefs from your code.
> > > > > > > >
> > > > > > > > But then it will increase binary code size.
> > > > > > >
> > > > > > > Using the member will increase code size. But I think the only place
> > > > > > > you need an #ifdef for that is when you include it in the driver
> > > > > > > struct. You can use __maybe_unused in the other place.
> > > > > > >
> > > > > > > Having the member will only increase memory usage, not code size.
> > > > > >
> > > > > > But static memory structures are part of the u-boot.bin binary and also
> > > > > > their usage increase code size (required copy, etc...), so at the end it
> > > > > > increase code size.
> > > > >
> > > > > From what I understand stdio_dev is allocated at runtime in BSS:
> > > > >
> > > > > struct stdio_dev *stdio_devices[] = { NULL, NULL, NULL };
> > > > >
> > > > > (the NULL stuff should not be there, but does nothing, I believe)
> > > > >
> > > > > So long as no code accesses your new member, then it should only
> > > > > affect the BSS size.
> > > >
> > > > Code of course has to access new member. How otherwise would be able to
> > > > call that new callbacks? E.g. all new code in patch 2/6 or 3/6.
> > >
> > > Yes, see below. Also, do check whether it actually adds code or not.
> > >
> > > >
> > > > > If you are very worried about it, you could use the technique in
> > > > > asm-generic/global_data.h to avoid #ifdefs in the C code:
> > > > >
> > > > > #ifdef CONFIG_GENERATE_ACPI_TABLE
> > > > > #define gd_acpi_start() gd->acpi_start
> > > > > #define gd_set_acpi_start(addr) gd->acpi_start = addr
> > > > > #else
> > > > > #define gd_acpi_start() 0UL
> > > > > #define gd_set_acpi_start(addr)
> > > > > #endif
> > > > >
> > > > > Regards,
> > > > > Simon
> > >
> > > Regards,
> > > Simon
> >
> > But in this case, it is needed to introduce a new special macro and hide
> > assigning code into it. In my opinion such macro with side effect and
> > worse than writing it explicitly - open coded to show what the code is
> > doing.
> 
> You can use an inline function if you prefer.

But it has still same issue, hiding conditional logic indirectly to
additional file. Some members would be assigned directly via = operator
and some via macro/inlinefunction is inconsistent.

> My main objection is to adding #ifdefs to C files. They are OK (for
> now) in driver struct declarations, where some members are optional.
> But I think it is worth going to some lengths to avoid them elsewhere.
> 
> +Tom Rini for thoughts on this
> 
> Regards,
> SImon

Any comments on this?
Simon Glass Aug. 31, 2022, 1:46 p.m. UTC | #11
Hi Pali,

On Wed, 31 Aug 2022 at 03:13, Pali Rohár <pali@kernel.org> wrote:
>
> On Thursday 25 August 2022 09:08:18 Simon Glass wrote:
> > Hi Pali,
> >
> > On Thu, 25 Aug 2022 at 08:20, Pali Rohár <pali@kernel.org> wrote:
> > >
> > > On Friday 12 August 2022 20:21:00 Simon Glass wrote:
> > > > Hi Pali,
> > > >
> > > > On Fri, 12 Aug 2022 at 09:17, Pali Rohár <pali@kernel.org> wrote:
> > > > >
> > > > > On Friday 12 August 2022 09:11:10 Simon Glass wrote:
> > > > > > Hi Pali,
> > > > > >
> > > > > > On Fri, 12 Aug 2022 at 03:01, Pali Rohár <pali@kernel.org> wrote:
> > > > > > >
> > > > > > > On Thursday 11 August 2022 18:08:46 Simon Glass wrote:
> > > > > > > > Hi Pali,
> > > > > > > >
> > > > > > > > On Thu, 11 Aug 2022 at 08:50, Pali Rohár <pali@kernel.org> wrote:
> > > > > > > > >
> > > > > > > > > On Thursday 11 August 2022 08:47:50 Simon Glass wrote:
> > > > > > > > > > > diff --git a/include/stdio_dev.h b/include/stdio_dev.h
> > > > > > > > > > > index 270fa2729fb2..06278366ae88 100644
> > > > > > > > > > > --- a/include/stdio_dev.h
> > > > > > > > > > > +++ b/include/stdio_dev.h
> > > > > > > > > > > @@ -37,6 +37,10 @@ struct stdio_dev {
> > > > > > > > > > >         void (*putc)(struct stdio_dev *dev, const char c);
> > > > > > > > > > >         /* To put a string (accelerator) */
> > > > > > > > > > >         void (*puts)(struct stdio_dev *dev, const char *s);
> > > > > > > > > > > +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
> > > > > > > > > >
> > > > > > > > > > I'd argue it isn't worth the #ifdef and we might as well have this
> > > > > > > > > > member here always. Then you can drop some #ifdefs from your code.
> > > > > > > > >
> > > > > > > > > But then it will increase binary code size.
> > > > > > > >
> > > > > > > > Using the member will increase code size. But I think the only place
> > > > > > > > you need an #ifdef for that is when you include it in the driver
> > > > > > > > struct. You can use __maybe_unused in the other place.
> > > > > > > >
> > > > > > > > Having the member will only increase memory usage, not code size.
> > > > > > >
> > > > > > > But static memory structures are part of the u-boot.bin binary and also
> > > > > > > their usage increase code size (required copy, etc...), so at the end it
> > > > > > > increase code size.
> > > > > >
> > > > > > From what I understand stdio_dev is allocated at runtime in BSS:
> > > > > >
> > > > > > struct stdio_dev *stdio_devices[] = { NULL, NULL, NULL };
> > > > > >
> > > > > > (the NULL stuff should not be there, but does nothing, I believe)
> > > > > >
> > > > > > So long as no code accesses your new member, then it should only
> > > > > > affect the BSS size.
> > > > >
> > > > > Code of course has to access new member. How otherwise would be able to
> > > > > call that new callbacks? E.g. all new code in patch 2/6 or 3/6.
> > > >
> > > > Yes, see below. Also, do check whether it actually adds code or not.
> > > >
> > > > >
> > > > > > If you are very worried about it, you could use the technique in
> > > > > > asm-generic/global_data.h to avoid #ifdefs in the C code:
> > > > > >
> > > > > > #ifdef CONFIG_GENERATE_ACPI_TABLE
> > > > > > #define gd_acpi_start() gd->acpi_start
> > > > > > #define gd_set_acpi_start(addr) gd->acpi_start = addr
> > > > > > #else
> > > > > > #define gd_acpi_start() 0UL
> > > > > > #define gd_set_acpi_start(addr)
> > > > > > #endif
> > > > > >
> > > > > > Regards,
> > > > > > Simon
> > > >
> > > > Regards,
> > > > Simon
> > >
> > > But in this case, it is needed to introduce a new special macro and hide
> > > assigning code into it. In my opinion such macro with side effect and
> > > worse than writing it explicitly - open coded to show what the code is
> > > doing.
> >
> > You can use an inline function if you prefer.
>
> But it has still same issue, hiding conditional logic indirectly to
> additional file. Some members would be assigned directly via = operator
> and some via macro/inlinefunction is inconsistent.

I've said everything I can say about this. If Tom has some thoughts
I'll leave it to him.

>
> > My main objection is to adding #ifdefs to C files. They are OK (for
> > now) in driver struct declarations, where some members are optional.
> > But I think it is worth going to some lengths to avoid them elsewhere.
> >
> > +Tom Rini for thoughts on this
> >
> > Regards,
> > SImon
>
> Any comments on this?

Regards,
Simon
Tom Rini Aug. 31, 2022, 1:55 p.m. UTC | #12
On Wed, Aug 31, 2022 at 07:46:58AM -0600, Simon Glass wrote:
> Hi Pali,
> 
> On Wed, 31 Aug 2022 at 03:13, Pali Rohár <pali@kernel.org> wrote:
> >
> > On Thursday 25 August 2022 09:08:18 Simon Glass wrote:
> > > Hi Pali,
> > >
> > > On Thu, 25 Aug 2022 at 08:20, Pali Rohár <pali@kernel.org> wrote:
> > > >
> > > > On Friday 12 August 2022 20:21:00 Simon Glass wrote:
> > > > > Hi Pali,
> > > > >
> > > > > On Fri, 12 Aug 2022 at 09:17, Pali Rohár <pali@kernel.org> wrote:
> > > > > >
> > > > > > On Friday 12 August 2022 09:11:10 Simon Glass wrote:
> > > > > > > Hi Pali,
> > > > > > >
> > > > > > > On Fri, 12 Aug 2022 at 03:01, Pali Rohár <pali@kernel.org> wrote:
> > > > > > > >
> > > > > > > > On Thursday 11 August 2022 18:08:46 Simon Glass wrote:
> > > > > > > > > Hi Pali,
> > > > > > > > >
> > > > > > > > > On Thu, 11 Aug 2022 at 08:50, Pali Rohár <pali@kernel.org> wrote:
> > > > > > > > > >
> > > > > > > > > > On Thursday 11 August 2022 08:47:50 Simon Glass wrote:
> > > > > > > > > > > > diff --git a/include/stdio_dev.h b/include/stdio_dev.h
> > > > > > > > > > > > index 270fa2729fb2..06278366ae88 100644
> > > > > > > > > > > > --- a/include/stdio_dev.h
> > > > > > > > > > > > +++ b/include/stdio_dev.h
> > > > > > > > > > > > @@ -37,6 +37,10 @@ struct stdio_dev {
> > > > > > > > > > > >         void (*putc)(struct stdio_dev *dev, const char c);
> > > > > > > > > > > >         /* To put a string (accelerator) */
> > > > > > > > > > > >         void (*puts)(struct stdio_dev *dev, const char *s);
> > > > > > > > > > > > +#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
> > > > > > > > > > >
> > > > > > > > > > > I'd argue it isn't worth the #ifdef and we might as well have this
> > > > > > > > > > > member here always. Then you can drop some #ifdefs from your code.
> > > > > > > > > >
> > > > > > > > > > But then it will increase binary code size.
> > > > > > > > >
> > > > > > > > > Using the member will increase code size. But I think the only place
> > > > > > > > > you need an #ifdef for that is when you include it in the driver
> > > > > > > > > struct. You can use __maybe_unused in the other place.
> > > > > > > > >
> > > > > > > > > Having the member will only increase memory usage, not code size.
> > > > > > > >
> > > > > > > > But static memory structures are part of the u-boot.bin binary and also
> > > > > > > > their usage increase code size (required copy, etc...), so at the end it
> > > > > > > > increase code size.
> > > > > > >
> > > > > > > From what I understand stdio_dev is allocated at runtime in BSS:
> > > > > > >
> > > > > > > struct stdio_dev *stdio_devices[] = { NULL, NULL, NULL };
> > > > > > >
> > > > > > > (the NULL stuff should not be there, but does nothing, I believe)
> > > > > > >
> > > > > > > So long as no code accesses your new member, then it should only
> > > > > > > affect the BSS size.
> > > > > >
> > > > > > Code of course has to access new member. How otherwise would be able to
> > > > > > call that new callbacks? E.g. all new code in patch 2/6 or 3/6.
> > > > >
> > > > > Yes, see below. Also, do check whether it actually adds code or not.
> > > > >
> > > > > >
> > > > > > > If you are very worried about it, you could use the technique in
> > > > > > > asm-generic/global_data.h to avoid #ifdefs in the C code:
> > > > > > >
> > > > > > > #ifdef CONFIG_GENERATE_ACPI_TABLE
> > > > > > > #define gd_acpi_start() gd->acpi_start
> > > > > > > #define gd_set_acpi_start(addr) gd->acpi_start = addr
> > > > > > > #else
> > > > > > > #define gd_acpi_start() 0UL
> > > > > > > #define gd_set_acpi_start(addr)
> > > > > > > #endif
> > > > > > >
> > > > > > > Regards,
> > > > > > > Simon
> > > > >
> > > > > Regards,
> > > > > Simon
> > > >
> > > > But in this case, it is needed to introduce a new special macro and hide
> > > > assigning code into it. In my opinion such macro with side effect and
> > > > worse than writing it explicitly - open coded to show what the code is
> > > > doing.
> > >
> > > You can use an inline function if you prefer.
> >
> > But it has still same issue, hiding conditional logic indirectly to
> > additional file. Some members would be assigned directly via = operator
> > and some via macro/inlinefunction is inconsistent.
> 
> I've said everything I can say about this. If Tom has some thoughts
> I'll leave it to him.
> 
> >
> > > My main objection is to adding #ifdefs to C files. They are OK (for
> > > now) in driver struct declarations, where some members are optional.
> > > But I think it is worth going to some lengths to avoid them elsewhere.
> > >
> > > +Tom Rini for thoughts on this
> > >
> > > Regards,
> > > SImon
> >
> > Any comments on this?

Given the plethora of tools to demonstrate that approach X results in
size change Y, I'm not sure why we're pondering if something will or
won't result in increases? I would like to see this series result in the
smallest increase in binary size on platforms that don't enable the
feature. An #ifdef isn't more or less readable than using some macro
instead, and decorators like __maybe_unused have their own impact on
code readability.
diff mbox series

Patch

diff --git a/common/Kconfig b/common/Kconfig
index e7914ca750a3..109741cc6c44 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -186,6 +186,12 @@  config PRE_CON_BUF_ADDR
 	  We should consider removing this option and allocating the memory
 	  in board_init_f_init_reserve() instead.
 
+config CONSOLE_FLUSH_SUPPORT
+	bool "Enable console flush support"
+	default y
+	help
+	  This enables compilation of flush() function for console flush support.
+
 config CONSOLE_MUX
 	bool "Enable console multiplexing"
 	default y if DM_VIDEO || VIDEO || LCD
diff --git a/common/console.c b/common/console.c
index dc071f1ed665..42415e34d16f 100644
--- a/common/console.c
+++ b/common/console.c
@@ -198,6 +198,9 @@  static int console_setfile(int file, struct stdio_dev * dev)
 		case stdout:
 			gd->jt->putc  = putc;
 			gd->jt->puts  = puts;
+#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
+			gd->jt->flush = flush;
+#endif
 			gd->jt->printf = printf;
 			break;
 		}
@@ -363,6 +366,19 @@  static void console_puts(int file, const char *s)
 	}
 }
 
+#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
+static void console_flush(int file)
+{
+	int i;
+	struct stdio_dev *dev;
+
+	for_each_console_dev(i, file, dev) {
+		if (dev->flush != NULL)
+			dev->flush(dev);
+	}
+}
+#endif
+
 #if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
 static inline void console_doenv(int file, struct stdio_dev *dev)
 {
@@ -412,6 +428,14 @@  static inline void console_puts(int file, const char *s)
 	stdio_devices[file]->puts(stdio_devices[file], s);
 }
 
+#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
+static inline void console_flush(int file)
+{
+	if (stdio_devices[file]->flush)
+		stdio_devices[file]->flush(stdio_devices[file]);
+}
+#endif
+
 #if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
 static inline void console_doenv(int file, struct stdio_dev *dev)
 {
@@ -525,6 +549,14 @@  void fputs(int file, const char *s)
 		console_puts(file, s);
 }
 
+#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
+void fflush(int file)
+{
+	if (file < MAX_FILES)
+		console_flush(file);
+}
+#endif
+
 int fprintf(int file, const char *fmt, ...)
 {
 	va_list args;
@@ -731,6 +763,37 @@  void puts(const char *s)
 	}
 }
 
+#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
+void flush(void)
+{
+	if (!gd)
+		return;
+
+	/* sandbox can send characters to stdout before it has a console */
+	if (IS_ENABLED(CONFIG_SANDBOX) && !(gd->flags & GD_FLG_SERIAL_READY)) {
+		os_flush();
+		return;
+	}
+
+	if (IS_ENABLED(CONFIG_DEBUG_UART) && !(gd->flags & GD_FLG_SERIAL_READY))
+		return;
+
+	if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT))
+		return;
+
+	if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
+		return;
+
+	if (!gd->have_console)
+		return;
+
+	if (gd->flags & GD_FLG_DEVINIT) {
+		/* Send to the standard output */
+		fflush(stdout);
+	}
+}
+#endif
+
 #ifdef CONFIG_CONSOLE_RECORD
 int console_record_init(void)
 {
diff --git a/include/_exports.h b/include/_exports.h
index f6df8b610734..1af946fac327 100644
--- a/include/_exports.h
+++ b/include/_exports.h
@@ -12,6 +12,9 @@ 
 	EXPORT_FUNC(tstc, int, tstc, void)
 	EXPORT_FUNC(putc, void, putc, const char)
 	EXPORT_FUNC(puts, void, puts, const char *)
+#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
+	EXPORT_FUNC(flush, void, flush, void)
+#endif
 	EXPORT_FUNC(printf, int, printf, const char*, ...)
 #if (defined(CONFIG_X86) && !defined(CONFIG_X86_64)) || defined(CONFIG_PPC)
 	EXPORT_FUNC(irq_install_handler, void, install_hdlr,
diff --git a/include/stdio.h b/include/stdio.h
index 1939a48f0fb6..3241e2d493fa 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -15,6 +15,11 @@  int tstc(void);
 		defined(CONFIG_SPL_SERIAL))
 void putc(const char c);
 void puts(const char *s);
+#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
+void flush(void);
+#else
+static inline void flush(void) {}
+#endif
 int __printf(1, 2) printf(const char *fmt, ...);
 int vprintf(const char *fmt, va_list args);
 #else
@@ -26,6 +31,10 @@  static inline void puts(const char *s)
 {
 }
 
+static inline void flush(void)
+{
+}
+
 static inline int __printf(1, 2) printf(const char *fmt, ...)
 {
 	return 0;
@@ -48,11 +57,17 @@  static inline int vprintf(const char *fmt, va_list args)
 /* stderr */
 #define eputc(c)		fputc(stderr, c)
 #define eputs(s)		fputs(stderr, s)
+#define eflush()		fflush(stderr)
 #define eprintf(fmt, args...)	fprintf(stderr, fmt, ##args)
 
 int __printf(2, 3) fprintf(int file, const char *fmt, ...);
 void fputs(int file, const char *s);
 void fputc(int file, const char c);
+#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
+void fflush(int file);
+#else
+static inline void fflush(int file) {}
+#endif
 int ftstc(int file);
 int fgetc(int file);
 
diff --git a/include/stdio_dev.h b/include/stdio_dev.h
index 270fa2729fb2..06278366ae88 100644
--- a/include/stdio_dev.h
+++ b/include/stdio_dev.h
@@ -37,6 +37,10 @@  struct stdio_dev {
 	void (*putc)(struct stdio_dev *dev, const char c);
 	/* To put a string (accelerator) */
 	void (*puts)(struct stdio_dev *dev, const char *s);
+#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
+	/* To flush output queue */
+	void (*flush)(struct stdio_dev *dev);
+#endif
 
 /* INPUT functions */