diff options
author | Kyösti Mälkki <kyosti.malkki@gmail.com> | 2013-08-12 16:11:34 +0300 |
---|---|---|
committer | Kyösti Mälkki <kyosti.malkki@gmail.com> | 2013-08-23 05:02:54 +0200 |
commit | d79914008abbc3eea4738d702ea7f3256e13327a (patch) | |
tree | cab2079aac864d82f10466ee5a058c4aa11407c3 | |
parent | 8ff3d68e93c74d82dc289036347c3da74c395c88 (diff) |
usbdebug: Block recursive calls of printk
When we create low-level debugging of EHCI controller registers,
we call printk() within printk(). In ramstage this would leave us
with deadlock waiting on the console spinlock.
Change-Id: Idbe029af9af76de27094bb2964c60d9ccfdd96e6
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: http://review.coreboot.org/3860
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
-rw-r--r-- | src/lib/usbdebug.c | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/src/lib/usbdebug.c b/src/lib/usbdebug.c index 4cd2987d6f..a5d3c37027 100644 --- a/src/lib/usbdebug.c +++ b/src/lib/usbdebug.c @@ -33,6 +33,7 @@ #define DBGP_EP_VALID (1<<0) #define DBGP_EP_ENABLED (1<<1) +#define DBGP_EP_BUSY (1<<2) #define DBGP_EP_STATMASK (DBGP_EP_VALID | DBGP_EP_ENABLED) struct dbgp_pipe @@ -44,8 +45,9 @@ struct dbgp_pipe }; #define DBGP_MAX_ENDPOINTS 4 -#define DBGP_CONSOLE_EPOUT 0 -#define DBGP_CONSOLE_EPIN 1 +#define DBGP_SETUP_EP0 0 /* Compulsory endpoint 0. */ +#define DBGP_CONSOLE_EPOUT 1 +#define DBGP_CONSOLE_EPIN 2 struct ehci_debug_info { u8 devnum; @@ -58,7 +60,9 @@ struct ehci_debug_info { }; #if CONFIG_DEBUG_USBDEBUG -# define dprintk(LEVEL, args...) printk(LEVEL, args) +static int dbgp_enabled(void); +# define dprintk(LEVEL, args...) \ + do { if (!dbgp_enabled()) printk(LEVEL, ##args); } while (0) #else # define dprintk(LEVEL, args...) do {} while(0) #endif @@ -580,6 +584,7 @@ try_next_port: info->ep_pipe[DBGP_CONSOLE_EPOUT].endpoint = dbgp_desc.bDebugOutEndpoint; info->ep_pipe[DBGP_CONSOLE_EPIN].endpoint = dbgp_desc.bDebugInEndpoint; + info->ep_pipe[DBGP_SETUP_EP0].status |= DBGP_EP_ENABLED | DBGP_EP_VALID; info->ep_pipe[DBGP_CONSOLE_EPOUT].status |= DBGP_EP_ENABLED | DBGP_EP_VALID; info->ep_pipe[DBGP_CONSOLE_EPIN].status |= DBGP_EP_ENABLED | DBGP_EP_VALID; return 0; @@ -606,23 +611,52 @@ next_debug_port: return -10; } +#if CONFIG_DEBUG_USBDEBUG +static int dbgp_enabled(void) +{ + struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0]; + return (globals->status & DBGP_EP_ENABLED); +} +#endif + +static int dbgp_try_get(struct dbgp_pipe *pipe) +{ + struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0]; + if (!dbgp_ep_is_active(pipe) || (globals->status & DBGP_EP_BUSY)) + return 0; + globals->status |= DBGP_EP_BUSY; + pipe->status |= DBGP_EP_BUSY; + return 1; +} + +static void dbgp_put(struct dbgp_pipe *pipe) +{ + struct dbgp_pipe *globals = &dbgp_ehci_info()->ep_pipe[DBGP_SETUP_EP0]; + globals->status &= ~DBGP_EP_BUSY; + pipe->status &= ~DBGP_EP_BUSY; +} + void usbdebug_tx_byte(struct dbgp_pipe *pipe, unsigned char data) { - if (dbgp_ep_is_active(pipe)) { - pipe->buf[pipe->bufidx++] = data; - if (pipe->bufidx >= 8) { - dbgp_bulk_write_x(pipe, pipe->buf, pipe->bufidx); - pipe->bufidx = 0; - } + if (!dbgp_try_get(pipe)) + return; + pipe->buf[pipe->bufidx++] = data; + if (pipe->bufidx >= 8) { + dbgp_bulk_write_x(pipe, pipe->buf, pipe->bufidx); + pipe->bufidx = 0; } + dbgp_put(pipe); } void usbdebug_tx_flush(struct dbgp_pipe *pipe) { - if (dbgp_ep_is_active(pipe) && pipe->bufidx > 0) { + if (!dbgp_try_get(pipe)) + return; + if (pipe->bufidx > 0) { dbgp_bulk_write_x(pipe, pipe->buf, pipe->bufidx); pipe->bufidx = 0; } + dbgp_put(pipe); } #if !defined(__PRE_RAM__) && !defined(__SMM__) |