Re: beagle hangs in uart3 disabling clocks

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Paul,

2010/10/5 Paul Walmsley <paul@xxxxxxxxx>:
> Hello Lei,
>
> On Tue, 5 Oct 2010, Ming Lei wrote:
>
>> 2010/10/5 Kevin Hilman <khilman@xxxxxxxxxxxxxxxxxxx>:
>> > Ming Lei <tom.leiming@xxxxxxxxx> writes:
>> >
>> >> 2010/10/4 Kevin Hilman <khilman@xxxxxxxxxxxxxxxxxxx>:
>> >>>
>> >>> Why?  What do you need from the PM branch that is not in l-o master?
>> >>
>> >> Seems master branch works fine for me, my beagle board doesn't hang
>> >> uart3 disabling clocks.
>> >
>> > Master branch and PM branch have exactly the same functionality for
>> > UART hwmods.  The problem was that you manually enabled DEBUG in
>> > omap_hwmod.c.
>>
>> Yes, you are correct. If DEBUG in omap_hwmod.c is enabled manually,
>> and pass the parameter of 'earlyprintk loglevel=8' to kernel from bootloader,
>> this issue can be triggered even with master branch.
>
> Does this experimental patch solve the problem, even if DEBUG is enabled
> in the hwmod code?
>
>
> - Paul
>
> From d928bd31c9c4ad16a044b244ef3d2ad3ed648f6f Mon Sep 17 00:00:00 2001
> From: Paul Walmsley <paul@xxxxxxxxx>
> Date: Tue, 5 Oct 2010 00:11:27 -0600
> Subject: [PATCH] RFC: omap serial: block console output while resetting earlyconsole UART
>
> Currently, no attempt is made to block console output while the
> earlyconsole UART is unavailable.  This can result in silent crashes
> that are very difficult to debug due to the lack of console output.
> This patch holds the console semaphore while resetting the active console
> UART, which causes all console output during that time to be buffered and
> then transmitted after the console semaphore is released.

Good works, this patch does fix the issue!

With the patch, even DEBUG in omap_hwmod.c is enabled manually
and 'earlyprintk loglevel=8' is passed to kernel, my beagle board can't
hang after 'uart3: disabling clocks' is printed.

>
> Not-yet-signed-off-by: Paul Walmsley <paul@xxxxxxxxx>
> ---
>  arch/arm/mach-omap2/serial.c |  100 ++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 100 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
> index 338e46a..577f8f9 100644
> --- a/arch/arm/mach-omap2/serial.c
> +++ b/arch/arm/mach-omap2/serial.c
> @@ -28,10 +28,13 @@
>  #include <linux/serial_8250.h>
>  #include <linux/pm_runtime.h>
>
> +#include <linux/console.h>
> +
>  #ifdef CONFIG_SERIAL_OMAP
>  #include <plat/omap-serial.h>
>  #endif
>
> +#include <plat/serial.h>
>  #include <plat/common.h>
>  #include <plat/board.h>
>  #include <plat/clock.h>
> @@ -39,6 +42,8 @@
>  #include <plat/omap_hwmod.h>
>  #include <plat/omap_device.h>
>
> +#include <asm/memory.h>
> +
>  #include "prm.h"
>  #include "pm.h"
>  #include "cm.h"
> @@ -51,6 +56,8 @@
>  #define UART_ERRATA_FIFO_FULL_ABORT    (0x1 << 0)
>  #define UART_ERRATA_i202_MDR1_ACCESS   (0x1 << 1)
>
> +#define uart_id_to_ttys_id(u)          (u - 1)
> +
>  /*
>  * NOTE: By default the serial timeout is disabled as it causes lost characters
>  * over the serial ports. This means that the UART clocks will stay on until
> @@ -106,6 +113,83 @@ static LIST_HEAD(uart_list);
>  static u8 num_uarts;
>
>  /*
> + * early_console_uart: if earlyconsole is enabled and active, the UART
> + * ID (e.g., 1, 2, 3, 4) will be stored here.  '0' means earlyconsole
> + * is disabled or some problem occurred during earlyconsole handling.
> + */
> +static int early_console_uart;
> +
> +#define for_each_console(con) \
> +       for (con = console_drivers; con != NULL; con = con->next)
> +
> +/* XXX belongs in kernel/printk.c or some earlyconsole file */
> +/* XXX The "earlycon" string is an ugly hack */
> +int _is_early_console_enabled(void)
> +{
> +       int ret = 0;
> +       struct console *c;
> +
> +       acquire_console_sem();
> +       for_each_console(c)
> +               if (!strcmp("earlycon", c->name))
> +                       ret = 1;
> +       release_console_sem();
> +
> +       return ret;
> +}
> +
> +/* XXX document */
> +static int _get_early_console_uart(void)
> +{
> +       u32 v;
> +       int u = -EINVAL;
> +
> +       v = __raw_readl(phys_to_virt(OMAP_UART_INFO));
> +       /* XXX see the OMAP debug-macro.S for this table */
> +       switch (v) {
> +       case 0:
> +       case OMAP2UART1:
> +               u = 1;
> +               break;
> +       case OMAP2UART2:
> +               u = 2;
> +               break;
> +       case OMAP2UART3:
> +       case OMAP3UART3:
> +       case OMAP4UART3:
> +               u = 3;
> +               break;
> +       case OMAP3UART4:
> +       case OMAP4UART4:
> +               u = 4;
> +               break;
> +       case ZOOM_UART:
> +               WARN(1, "omap serial: ZOOM UART in use - does that go through "
> +                    "the OMAP serial code?\n");
> +               break;
> +       default:
> +               WARN(1, "omap serial: unknown serial port in use!\n");
> +       }
> +
> +       return u;
> +}
> +
> +/* XXX document */
> +static void _store_early_console_uart_id(void)
> +{
> +       int uart_id;
> +
> +       if (_is_early_console_enabled()) {
> +               uart_id = _get_early_console_uart();
> +               if (uart_id > 0) {
> +                       early_console_uart = uart_id;
> +                       pr_info("omap serial: early console active on UART%d (ttyS%d)\n",
> +                               uart_id, uart_id_to_ttys_id(uart_id));
> +               }
> +       }
> +}
> +
> +/*
>  * Since these idle/enable hooks are used in the idle path itself
>  * which has interrupts disabled, use the non-locking versions of
>  * the hwmod enable/disable functions.
> @@ -801,6 +885,17 @@ void __init omap_serial_init_port(int port)
>        oh->dev_attr = uart;
>
>        /*
> +        * XXX How do we know whether the console is on this UART or not?
> +        * We should only call acquire_console_sem() if the console is on
> +        * this UART.
> +        *
> +        * Of course, the console is not the only thing that could be using
> +        * this UART.
> +        */
> +       if (uart->num == uart_id_to_ttys_id(early_console_uart))
> +               acquire_console_sem();
> +
> +       /*
>         * Because of early UART probing, UART did not get idled
>         * on init.  Now that omap_device is ready, ensure full idle
>         * before doing omap_device_enable().
> @@ -824,6 +919,9 @@ void __init omap_serial_init_port(int port)
>        omap_uart_block_sleep(uart);
>        uart->timeout = DEFAULT_TIMEOUT;
>
> +       if (uart->num == uart_id_to_ttys_id(early_console_uart))
> +               release_console_sem();
> +
>        if ((cpu_is_omap34xx() && uart->padconf) ||
>            (uart->wk_en && uart->wk_mask)) {
>                device_init_wakeup(&od->pdev.dev, true);
> @@ -846,6 +944,8 @@ void __init omap_serial_init(void)
>  {
>        struct omap_uart_state *uart;
>
> +       _store_early_console_uart_id();
> +
>        list_for_each_entry(uart, &uart_list, node)
>                omap_serial_init_port(uart->num);
>  }
> --
> 1.7.1
>


thanks,
-- 
Lei Ming
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux